generated from MrSphay/codex-agent-repository-kit
This commit is contained in:
31
.gitea/workflows/build.yml
Normal file
31
.gitea/workflows/build.yml
Normal file
@@ -0,0 +1,31 @@
|
||||
name: Build
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Java
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: '21'
|
||||
|
||||
- name: Build
|
||||
run: ./gradlew build --stacktrace
|
||||
|
||||
- name: Upload mod jar
|
||||
uses: actions/upload-artifact@v3
|
||||
if: always()
|
||||
with:
|
||||
name: explosionoverhaul-neoforge-build
|
||||
path: |
|
||||
build/libs/**
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -4,6 +4,7 @@ run/
|
||||
out/
|
||||
|
||||
_mdk/
|
||||
_decompiled/
|
||||
tools/
|
||||
upstream/
|
||||
decompiled/
|
||||
|
||||
184
build.gradle
Normal file
184
build.gradle
Normal file
@@ -0,0 +1,184 @@
|
||||
plugins {
|
||||
id 'java-library'
|
||||
id 'maven-publish'
|
||||
id 'net.neoforged.moddev' version '2.0.141'
|
||||
id 'idea'
|
||||
}
|
||||
|
||||
tasks.named('wrapper', Wrapper).configure {
|
||||
// Define wrapper values here so as to not have to always do so when updating gradlew.properties.
|
||||
// Switching this to Wrapper.DistributionType.ALL will download the full gradle sources that comes with
|
||||
// documentation attached on cursor hover of gradle classes and methods. However, this comes with increased
|
||||
// file size for Gradle. If you do switch this to ALL, run the Gradle wrapper task twice afterwards.
|
||||
// (Verify by checking gradle/wrapper/gradle-wrapper.properties to see if distributionUrl now points to `-all`)
|
||||
distributionType = Wrapper.DistributionType.BIN
|
||||
}
|
||||
|
||||
version = mod_version
|
||||
group = mod_group_id
|
||||
|
||||
sourceSets.main.resources {
|
||||
// Include resources generated by data generators.
|
||||
srcDir('src/generated/resources')
|
||||
|
||||
// Exclude common development only resources from finalized outputs
|
||||
exclude("**/*.bbmodel") // BlockBench project files
|
||||
exclude("src/generated/**/.cache") // datagen cache files
|
||||
}
|
||||
|
||||
repositories {
|
||||
maven {
|
||||
name = "CurseMaven"
|
||||
url = "https://cursemaven.com"
|
||||
}
|
||||
maven {
|
||||
name = "GeckoLib"
|
||||
url = "https://dl.cloudsmith.io/public/geckolib3/geckolib/maven/"
|
||||
}
|
||||
maven {
|
||||
name = "TerraformersMC"
|
||||
url = "https://maven.terraformersmc.com/releases/"
|
||||
}
|
||||
}
|
||||
|
||||
base {
|
||||
archivesName = mod_id
|
||||
}
|
||||
|
||||
// Mojang ships Java 21 to end users in 1.21.1, so mods should target Java 21.
|
||||
java.toolchain.languageVersion = JavaLanguageVersion.of(21)
|
||||
|
||||
neoForge {
|
||||
// Specify the version of NeoForge to use.
|
||||
version = project.neo_version
|
||||
|
||||
parchment {
|
||||
mappingsVersion = project.parchment_mappings_version
|
||||
minecraftVersion = project.parchment_minecraft_version
|
||||
}
|
||||
|
||||
// This line is optional. Access Transformers are automatically detected
|
||||
// accessTransformers = project.files('src/main/resources/META-INF/accesstransformer.cfg')
|
||||
|
||||
// Default run configurations.
|
||||
// These can be tweaked, removed, or duplicated as needed.
|
||||
runs {
|
||||
client {
|
||||
client()
|
||||
|
||||
// Comma-separated list of namespaces to load gametests from. Empty = all namespaces.
|
||||
systemProperty 'neoforge.enabledGameTestNamespaces', project.mod_id
|
||||
}
|
||||
|
||||
server {
|
||||
server()
|
||||
programArgument '--nogui'
|
||||
systemProperty 'neoforge.enabledGameTestNamespaces', project.mod_id
|
||||
}
|
||||
|
||||
// This run config launches GameTestServer and runs all registered gametests, then exits.
|
||||
// By default, the server will crash when no gametests are provided.
|
||||
// The gametest system is also enabled by default for other run configs under the /test command.
|
||||
gameTestServer {
|
||||
type = "gameTestServer"
|
||||
systemProperty 'neoforge.enabledGameTestNamespaces', project.mod_id
|
||||
}
|
||||
|
||||
data {
|
||||
data()
|
||||
|
||||
// example of overriding the workingDirectory set in configureEach above, uncomment if you want to use it
|
||||
// gameDirectory = project.file('run-data')
|
||||
|
||||
// Specify the modid for data generation, where to output the resulting resource, and where to look for existing resources.
|
||||
programArguments.addAll '--mod', project.mod_id, '--all', '--output', file('src/generated/resources/').getAbsolutePath(), '--existing', file('src/main/resources/').getAbsolutePath()
|
||||
}
|
||||
|
||||
// applies to all the run configs above
|
||||
configureEach {
|
||||
// Recommended logging data for a userdev environment
|
||||
// The markers can be added/remove as needed separated by commas.
|
||||
// "SCAN": For mods scan.
|
||||
// "REGISTRIES": For firing of registry events.
|
||||
// "REGISTRYDUMP": For getting the contents of all registries.
|
||||
systemProperty 'forge.logging.markers', 'REGISTRIES'
|
||||
|
||||
// Recommended logging level for the console
|
||||
// You can set various levels here.
|
||||
// Please read: https://stackoverflow.com/questions/2031163/when-to-use-the-different-log-levels
|
||||
logLevel = org.slf4j.event.Level.DEBUG
|
||||
}
|
||||
}
|
||||
|
||||
mods {
|
||||
// define mod <-> source bindings
|
||||
// these are used to tell the game which sources are for which mod
|
||||
// multi mod projects should define one per mod
|
||||
"${mod_id}" {
|
||||
sourceSet(sourceSets.main)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sets up a dependency configuration called 'localRuntime'.
|
||||
// This configuration should be used instead of 'runtimeOnly' to declare
|
||||
// a dependency that will be present for runtime testing but that is
|
||||
// "optional", meaning it will not be pulled by dependents of this mod.
|
||||
configurations {
|
||||
runtimeClasspath.extendsFrom localRuntime
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation "curse.maven:cloth-config-348521:5623420"
|
||||
implementation "curse.maven:geckolib-388172:5763144"
|
||||
}
|
||||
|
||||
// This block of code expands all declared replace properties in the specified resource targets.
|
||||
// A missing property will result in an error. Properties are expanded using ${} Groovy notation.
|
||||
var generateModMetadata = tasks.register("generateModMetadata", ProcessResources) {
|
||||
var replaceProperties = [
|
||||
minecraft_version : minecraft_version,
|
||||
minecraft_version_range: minecraft_version_range,
|
||||
neo_version : neo_version,
|
||||
loader_version_range : loader_version_range,
|
||||
mod_id : mod_id,
|
||||
mod_name : mod_name,
|
||||
mod_license : mod_license,
|
||||
mod_version : mod_version,
|
||||
]
|
||||
inputs.properties replaceProperties
|
||||
expand replaceProperties
|
||||
from "src/main/templates"
|
||||
into "build/generated/sources/modMetadata"
|
||||
}
|
||||
// Include the output of "generateModMetadata" as an input directory for the build
|
||||
// this works with both building through Gradle and the IDE.
|
||||
sourceSets.main.resources.srcDir generateModMetadata
|
||||
// To avoid having to run "generateModMetadata" manually, make it run on every project reload
|
||||
neoForge.ideSyncTask generateModMetadata
|
||||
|
||||
// Example configuration to allow publishing using the maven-publish plugin
|
||||
publishing {
|
||||
publications {
|
||||
register('mavenJava', MavenPublication) {
|
||||
from components.java
|
||||
}
|
||||
}
|
||||
repositories {
|
||||
maven {
|
||||
url "file://${project.projectDir}/repo"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tasks.withType(JavaCompile).configureEach {
|
||||
options.encoding = 'UTF-8' // Use the UTF-8 charset for Java compilation
|
||||
}
|
||||
|
||||
// IDEA no longer automatically downloads sources/javadoc jars for dependencies, so we need to explicitly enable the behavior.
|
||||
idea {
|
||||
module {
|
||||
downloadSources = true
|
||||
downloadJavadoc = true
|
||||
}
|
||||
}
|
||||
39
gradle.properties
Normal file
39
gradle.properties
Normal file
@@ -0,0 +1,39 @@
|
||||
# Sets default memory used for gradle commands. Can be overridden by user or command line properties.
|
||||
org.gradle.jvmargs=-Xmx3G
|
||||
org.gradle.daemon=true
|
||||
org.gradle.parallel=true
|
||||
org.gradle.caching=true
|
||||
org.gradle.configuration-cache=true
|
||||
|
||||
#read more on this at https://github.com/neoforged/ModDevGradle?tab=readme-ov-file#better-minecraft-parameter-names--javadoc-parchment
|
||||
# you can also find the latest versions at: https://parchmentmc.org/docs/getting-started
|
||||
parchment_minecraft_version=1.21.1
|
||||
parchment_mappings_version=2024.11.17
|
||||
# Environment Properties
|
||||
# You can find the latest versions here: https://projects.neoforged.net/neoforged/neoforge
|
||||
# The Minecraft version must agree with the Neo version to get a valid artifact
|
||||
minecraft_version=1.21.1
|
||||
# The Minecraft version range can use any release version of Minecraft as bounds.
|
||||
# Snapshots, pre-releases, and release candidates are not guaranteed to sort properly
|
||||
# as they do not follow standard versioning conventions.
|
||||
minecraft_version_range=[1.21.1]
|
||||
# The Neo version must agree with the Minecraft version to get a valid artifact
|
||||
neo_version=21.1.228
|
||||
# The loader version range can only use the major version of FML as bounds
|
||||
loader_version_range=[1,)
|
||||
|
||||
## Mod Properties
|
||||
|
||||
# The unique mod identifier for the mod. Must be lowercase in English locale. Must fit the regex [a-z][a-z0-9_]{1,63}
|
||||
# Must match the String constant located in the main mod class annotated with @Mod.
|
||||
mod_id=explosionoverhaul
|
||||
# The human-readable display name for the mod.
|
||||
mod_name=Explosion Overhaul
|
||||
# The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default.
|
||||
mod_license=All Rights Reserved
|
||||
# The mod version. See https://semver.org/
|
||||
mod_version=0.2.3.0-neoforge-1.21.1
|
||||
# The group ID for the mod. It is only important when publishing as an artifact to a Maven repository.
|
||||
# This should match the base package used for the mod sources.
|
||||
# See https://maven.apache.org/guides/mini/guide-naming-conventions.html
|
||||
mod_group_id=com.vinlanx.explosionoverhaul
|
||||
7
gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
7
gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.1-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
251
gradlew
vendored
Normal file
251
gradlew
vendored
Normal file
@@ -0,0 +1,251 @@
|
||||
#!/bin/sh
|
||||
|
||||
#
|
||||
# Copyright © 2015-2021 the original authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
# 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/HEAD/platforms/jvm/plugins-application/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
|
||||
|
||||
# Resolve links: $0 may be a link
|
||||
app_path=$0
|
||||
|
||||
# Need this for daisy-chained symlinks.
|
||||
while
|
||||
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
|
||||
[ -h "$app_path" ]
|
||||
do
|
||||
ls=$( ls -ld "$app_path" )
|
||||
link=${ls#*' -> '}
|
||||
case $link in #(
|
||||
/*) app_path=$link ;; #(
|
||||
*) app_path=$APP_HOME$link ;;
|
||||
esac
|
||||
done
|
||||
|
||||
# This is normally unused
|
||||
# shellcheck disable=SC2034
|
||||
APP_BASE_NAME=${0##*/}
|
||||
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD=maximum
|
||||
|
||||
warn () {
|
||||
echo "$*"
|
||||
} >&2
|
||||
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
} >&2
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "$( uname )" in #(
|
||||
CYGWIN* ) cygwin=true ;; #(
|
||||
Darwin* ) darwin=true ;; #(
|
||||
MSYS* | MINGW* ) msys=true ;; #(
|
||||
NONSTOP* ) nonstop=true ;;
|
||||
esac
|
||||
|
||||
CLASSPATH="\\\"\\\""
|
||||
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD=$JAVA_HOME/jre/sh/java
|
||||
else
|
||||
JAVACMD=$JAVA_HOME/bin/java
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD=java
|
||||
if ! command -v java >/dev/null 2>&1
|
||||
then
|
||||
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||
case $MAX_FD in #(
|
||||
max*)
|
||||
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC2039,SC3045
|
||||
MAX_FD=$( ulimit -H -n ) ||
|
||||
warn "Could not query maximum file descriptor limit"
|
||||
esac
|
||||
case $MAX_FD in #(
|
||||
'' | soft) :;; #(
|
||||
*)
|
||||
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC2039,SC3045
|
||||
ulimit -n "$MAX_FD" ||
|
||||
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||
esac
|
||||
fi
|
||||
|
||||
# Collect all arguments for the java command, stacking in reverse order:
|
||||
# * args from the command line
|
||||
# * the main class name
|
||||
# * -classpath
|
||||
# * -D...appname settings
|
||||
# * --module-path (only if needed)
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
|
||||
|
||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||
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
|
||||
|
||||
|
||||
# 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"'
|
||||
|
||||
# Collect all arguments for the java command:
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
||||
# and any embedded shellness will be escaped.
|
||||
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
|
||||
# treated as '${Hostname}' itself on the command line.
|
||||
|
||||
set -- \
|
||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||
-classpath "$CLASSPATH" \
|
||||
-jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
|
||||
"$@"
|
||||
|
||||
# Stop when "xargs" is not available.
|
||||
if ! command -v xargs >/dev/null 2>&1
|
||||
then
|
||||
die "xargs is not available"
|
||||
fi
|
||||
|
||||
# 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" "$@"
|
||||
94
gradlew.bat
vendored
Normal file
94
gradlew.bat
vendored
Normal file
@@ -0,0 +1,94 @@
|
||||
@rem
|
||||
@rem Copyright 2015 the original author or authors.
|
||||
@rem
|
||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@rem you may not use this file except in compliance with the License.
|
||||
@rem You may obtain a copy of the License at
|
||||
@rem
|
||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||
@rem
|
||||
@rem Unless required by applicable law or agreed to in writing, software
|
||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
@rem SPDX-License-Identifier: Apache-2.0
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%"=="" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%"=="" set DIRNAME=.
|
||||
@rem This is normally unused
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if %ERRORLEVEL% equ 0 goto execute
|
||||
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
goto fail
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if %ERRORLEVEL% equ 0 goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
set EXIT_CODE=%ERRORLEVEL%
|
||||
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
||||
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
||||
exit /b %EXIT_CODE%
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
||||
9
settings.gradle
Normal file
9
settings.gradle
Normal file
@@ -0,0 +1,9 @@
|
||||
pluginManagement {
|
||||
repositories {
|
||||
gradlePluginPortal()
|
||||
}
|
||||
}
|
||||
|
||||
plugins {
|
||||
id 'org.gradle.toolchains.foojay-resolver-convention' version '1.0.0'
|
||||
}
|
||||
@@ -0,0 +1,375 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul;
|
||||
|
||||
import com.vinlanx.explosionoverhaul.CameraShakePacket;
|
||||
import com.vinlanx.explosionoverhaul.Config;
|
||||
import com.vinlanx.explosionoverhaul.DripstoneEffects;
|
||||
import com.vinlanx.explosionoverhaul.ExplosionOverhaul;
|
||||
import com.vinlanx.explosionoverhaul.ModSounds;
|
||||
import com.vinlanx.explosionoverhaul.PacketHandler;
|
||||
import com.vinlanx.explosionoverhaul.PlayTrackedSoundPacket;
|
||||
import com.vinlanx.explosionoverhaul.RedstoneLampEffects;
|
||||
import com.vinlanx.explosionoverhaul.ServerExplosionHandler;
|
||||
import com.vinlanx.explosionoverhaul.SpawnAmbientCaveDustPacket;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.sounds.SoundEvent;
|
||||
import net.minecraft.sounds.SoundSource;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.neoforged.neoforge.network.PacketDistributor;
|
||||
import net.neoforged.neoforge.registries.ForgeRegistries;
|
||||
|
||||
public class AmbientExplosionManager {
|
||||
private static final Map<UUID, PlayerTimer> playerTimers = new HashMap<UUID, PlayerTimer>();
|
||||
|
||||
public static void onServerTick(ServerLevel level) {
|
||||
if (!((Boolean)Config.COMMON.ambient.enableAmbientExplosions.get()).booleanValue()) {
|
||||
if (!playerTimers.isEmpty()) {
|
||||
playerTimers.clear();
|
||||
}
|
||||
return;
|
||||
}
|
||||
for (ServerPlayer player : level.m_6907_()) {
|
||||
PlayerTimer timer = playerTimers.computeIfAbsent(player.m_20148_(), id -> new PlayerTimer(level.m_213780_()));
|
||||
timer.tick(player);
|
||||
}
|
||||
}
|
||||
|
||||
public static void onPlayerLoggedIn(ServerPlayer player) {
|
||||
playerTimers.put(player.m_20148_(), new PlayerTimer(player.f_8924_.m_129783_().m_213780_()));
|
||||
}
|
||||
|
||||
public static void onPlayerLoggedOut(ServerPlayer player) {
|
||||
playerTimers.remove(player.m_20148_());
|
||||
}
|
||||
|
||||
private static ServerExplosionHandler.CameraShakeProfile determineCameraShakeProfile(float power, double distance, boolean playerInCave, ServerLevel level) {
|
||||
float intensity = 0.0f;
|
||||
int baseDuration = 20;
|
||||
float pushIntensity = 0.0f;
|
||||
int closeDistance = 50;
|
||||
int mediumDistance = 500;
|
||||
int farDistance = 1000;
|
||||
int superFarDistance = 5000;
|
||||
int powerCategory = power <= 3.0f ? 1 : (power <= 6.0f ? 2 : (power <= 14.0f ? 3 : (power <= 30.0f ? 4 : (power <= 60.0f ? 5 : (power <= 99.0f ? 6 : 7)))));
|
||||
int shakeLevel = 0;
|
||||
if (distance <= 50.0) {
|
||||
if (powerCategory >= 7) {
|
||||
shakeLevel = 5;
|
||||
baseDuration = 50;
|
||||
} else if (powerCategory == 6) {
|
||||
shakeLevel = 5;
|
||||
baseDuration = 40;
|
||||
} else if (powerCategory == 5) {
|
||||
shakeLevel = 4;
|
||||
baseDuration = 35;
|
||||
} else if (powerCategory == 4) {
|
||||
shakeLevel = 4;
|
||||
baseDuration = 30;
|
||||
} else if (powerCategory == 3) {
|
||||
shakeLevel = 3;
|
||||
baseDuration = 25;
|
||||
} else if (powerCategory == 2) {
|
||||
shakeLevel = 3;
|
||||
baseDuration = 20;
|
||||
} else if (powerCategory == 1) {
|
||||
shakeLevel = 2;
|
||||
baseDuration = 15;
|
||||
}
|
||||
} else if (distance <= 500.0) {
|
||||
if (powerCategory >= 7) {
|
||||
shakeLevel = 4;
|
||||
baseDuration = 35;
|
||||
} else if (powerCategory == 6) {
|
||||
shakeLevel = 4;
|
||||
baseDuration = 30;
|
||||
} else if (powerCategory == 5) {
|
||||
shakeLevel = 3;
|
||||
baseDuration = 25;
|
||||
} else if (powerCategory == 4) {
|
||||
shakeLevel = 3;
|
||||
baseDuration = 20;
|
||||
} else if (powerCategory <= 3) {
|
||||
shakeLevel = 2;
|
||||
baseDuration = 15;
|
||||
}
|
||||
} else if (distance <= 1000.0) {
|
||||
if (powerCategory >= 7) {
|
||||
shakeLevel = 3;
|
||||
baseDuration = 25;
|
||||
} else if (powerCategory == 6) {
|
||||
shakeLevel = 3;
|
||||
baseDuration = 20;
|
||||
} else if (powerCategory == 5) {
|
||||
shakeLevel = 2;
|
||||
baseDuration = 15;
|
||||
} else if (powerCategory == 4) {
|
||||
shakeLevel = 2;
|
||||
baseDuration = 10;
|
||||
}
|
||||
} else if (distance <= 5000.0) {
|
||||
if (powerCategory >= 7) {
|
||||
shakeLevel = 3;
|
||||
baseDuration = 20;
|
||||
} else if (powerCategory == 6) {
|
||||
shakeLevel = 2;
|
||||
baseDuration = 15;
|
||||
} else if (powerCategory == 5) {
|
||||
shakeLevel = 1;
|
||||
baseDuration = 10;
|
||||
}
|
||||
}
|
||||
switch (shakeLevel) {
|
||||
case 1: {
|
||||
intensity = 0.06f;
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
intensity = 0.18f;
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
intensity = 0.4f;
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
intensity = 0.65f;
|
||||
break;
|
||||
}
|
||||
case 5: {
|
||||
intensity = 0.9f;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
intensity = 0.0f;
|
||||
baseDuration = 0;
|
||||
}
|
||||
}
|
||||
if (playerInCave && intensity > 0.0f && shakeLevel >= 2) {
|
||||
float basePush = 0.02f + (float)shakeLevel * 0.015f;
|
||||
pushIntensity = Math.min(basePush * (power / 8.0f), 0.25f);
|
||||
pushIntensity = Math.max(0.04f, pushIntensity);
|
||||
}
|
||||
if (intensity > 0.01f && baseDuration < 5) {
|
||||
baseDuration = 5;
|
||||
}
|
||||
if (intensity < 0.01f) {
|
||||
intensity = 0.0f;
|
||||
baseDuration = 0;
|
||||
pushIntensity = 0.0f;
|
||||
}
|
||||
return new ServerExplosionHandler.CameraShakeProfile(intensity, baseDuration, pushIntensity);
|
||||
}
|
||||
|
||||
private static class PlayerTimer {
|
||||
private final RandomSource random;
|
||||
private int timeUntilNextEvent;
|
||||
|
||||
PlayerTimer(RandomSource random) {
|
||||
this.random = random;
|
||||
this.resetTimer();
|
||||
}
|
||||
|
||||
private void resetTimer() {
|
||||
int max;
|
||||
int min = (Integer)Config.COMMON.ambient.minTimeBetweenExplosions.get();
|
||||
this.timeUntilNextEvent = min >= (max = ((Integer)Config.COMMON.ambient.maxTimeBetweenExplosions.get()).intValue()) ? min : this.random.m_216339_(min, max);
|
||||
}
|
||||
|
||||
public void tick(ServerPlayer player) {
|
||||
if (this.timeUntilNextEvent-- <= 0) {
|
||||
this.generateAndPlayAmbientEventForPlayer(player);
|
||||
this.resetTimer();
|
||||
}
|
||||
}
|
||||
|
||||
private void generateAndPlayAmbientEventForPlayer(ServerPlayer player) {
|
||||
int shellingWeight;
|
||||
int chainWeight;
|
||||
Config.Common.Ambient.Scenarios scenarios = Config.COMMON.ambient.scenarios;
|
||||
int singleWeight = (Integer)scenarios.singleExplosionWeight.get();
|
||||
int totalWeight = singleWeight + (chainWeight = ((Integer)scenarios.chainReactionWeight.get()).intValue()) + (shellingWeight = ((Integer)scenarios.shellingWeight.get()).intValue());
|
||||
if (totalWeight <= 0) {
|
||||
return;
|
||||
}
|
||||
int roll = this.random.m_188503_(totalWeight);
|
||||
AmbientEventType eventType = (roll -= singleWeight) < 0 ? AmbientEventType.SINGLE : ((roll -= chainWeight) < 0 ? AmbientEventType.CHAIN_REACTION : AmbientEventType.SHELLING);
|
||||
Vec3 eventPos = this.generateEventPosition(player);
|
||||
SoundEnvironment chosenEnv = this.determineSoundEnvironment(player, eventPos);
|
||||
if (chosenEnv == null) {
|
||||
return;
|
||||
}
|
||||
boolean playerInHouse = ServerExplosionHandler.isInHouse(player.m_284548_(), player.m_20183_(), player.m_146892_().f_82480_);
|
||||
BlockPos dripstoneCenter = player.m_20183_();
|
||||
int explosionPower = (int)Math.ceil(this.generatePower());
|
||||
DripstoneEffects.handleDripstoneFall(player.m_284548_(), dripstoneCenter, explosionPower, player.m_217043_());
|
||||
ArrayList<AmbientSoundData> soundsToPlay = new ArrayList<AmbientSoundData>();
|
||||
switch (eventType) {
|
||||
case SINGLE: {
|
||||
float power = this.generatePower();
|
||||
if (!(power > 0.0f)) break;
|
||||
soundsToPlay.add(new AmbientSoundData(power, 0L, false));
|
||||
break;
|
||||
}
|
||||
case CHAIN_REACTION: {
|
||||
int minShots = (Integer)scenarios.minChainReactionShots.get();
|
||||
int maxShots = (Integer)scenarios.maxChainReactionShots.get();
|
||||
int shotCount = minShots >= maxShots ? minShots : this.random.m_216339_(minShots, maxShots + 1);
|
||||
long cumulativeDelay = 0L;
|
||||
for (int i = 0; i < shotCount; ++i) {
|
||||
float progress = shotCount > 1 ? (float)i / (float)(shotCount - 1) : 1.0f;
|
||||
float power = Mth.m_14179_((float)(progress * progress), (float)1.0f, (float)40.0f) + this.random.m_188501_() * 4.0f;
|
||||
int minDelay = (Integer)scenarios.minTimeBetweenChainShots.get();
|
||||
int maxDelay = (Integer)scenarios.maxTimeBetweenChainShots.get();
|
||||
soundsToPlay.add(new AmbientSoundData(power, cumulativeDelay += minDelay >= maxDelay ? (long)minDelay : (long)this.random.m_216339_(minDelay, maxDelay + 1), false));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SHELLING: {
|
||||
float shotPower = 1.0f + this.random.m_188501_() * 3.0f;
|
||||
float impactPower = 5.0f + this.random.m_188501_() * 10.0f;
|
||||
int minDelay = (Integer)scenarios.minShellingDelay.get();
|
||||
int maxDelay = (Integer)scenarios.maxShellingDelay.get();
|
||||
long impactDelay = minDelay >= maxDelay ? (long)minDelay : (long)this.random.m_216339_(minDelay, maxDelay + 1);
|
||||
soundsToPlay.add(new AmbientSoundData(shotPower, 0L, true));
|
||||
soundsToPlay.add(new AmbientSoundData(impactPower, impactDelay, false));
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (AmbientSoundData soundData : soundsToPlay) {
|
||||
this.playSoundForEnvironment(player, player.m_284548_(), soundData.power(), chosenEnv, playerInHouse, soundData.delay(), soundData.isShellingShot(), eventPos);
|
||||
}
|
||||
}
|
||||
|
||||
private Vec3 generateEventPosition(ServerPlayer player) {
|
||||
int maxDst;
|
||||
int minDst = (Integer)Config.COMMON.ambient.minExplosionDistance.get();
|
||||
double distance = minDst >= (maxDst = ((Integer)Config.COMMON.ambient.maxExplosionDistance.get()).intValue()) ? (double)minDst : (double)minDst + this.random.m_188500_() * (double)(maxDst - minDst);
|
||||
double angle = this.random.m_188500_() * 2.0 * Math.PI;
|
||||
double x = player.m_20185_() + Math.cos(angle) * distance;
|
||||
double z = player.m_20189_() + Math.sin(angle) * distance;
|
||||
double y = player.m_20186_();
|
||||
return new Vec3(x, y, z);
|
||||
}
|
||||
|
||||
private float generatePower() {
|
||||
Config.Common.Ambient.PowerTiers weights = Config.COMMON.ambient.powerTiers;
|
||||
int totalWeight = (Integer)weights.tier1_weight.get() + (Integer)weights.tier2_weight.get() + (Integer)weights.tier3_weight.get() + (Integer)weights.tier4_weight.get() + (Integer)weights.tier5_weight.get();
|
||||
if (totalWeight <= 0) {
|
||||
return 0.0f;
|
||||
}
|
||||
int roll = this.random.m_188503_(totalWeight);
|
||||
if ((roll -= ((Integer)weights.tier1_weight.get()).intValue()) < 0) {
|
||||
return 1.0f + this.random.m_188501_() * 3.0f;
|
||||
}
|
||||
if ((roll -= ((Integer)weights.tier2_weight.get()).intValue()) < 0) {
|
||||
return 5.0f + this.random.m_188501_() * 10.0f;
|
||||
}
|
||||
if ((roll -= ((Integer)weights.tier3_weight.get()).intValue()) < 0) {
|
||||
return 16.0f + this.random.m_188501_() * 24.0f;
|
||||
}
|
||||
if ((roll -= ((Integer)weights.tier4_weight.get()).intValue()) < 0) {
|
||||
return 41.0f + this.random.m_188501_() * 39.0f;
|
||||
}
|
||||
if ((roll -= ((Integer)weights.tier5_weight.get()).intValue()) < 0) {
|
||||
return 81.0f + this.random.m_188501_() * (((Double)Config.COMMON.ambient.maxAmbientExplosionPower.get()).floatValue() - 81.0f);
|
||||
}
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
private SoundEnvironment determineSoundEnvironment(ServerPlayer player, Vec3 eventPos) {
|
||||
boolean isPlayerInCave = ServerExplosionHandler.isInNaturalCave(player.m_284548_(), player.m_20183_());
|
||||
Config.Common.Ambient.SoundTypes soundTypes = Config.COMMON.ambient.soundTypes;
|
||||
if (isPlayerInCave) {
|
||||
return (Boolean)soundTypes.enableCaveSounds.get() != false ? SoundEnvironment.CAVE : null;
|
||||
}
|
||||
return (Boolean)soundTypes.enableSurfaceSounds.get() != false ? SoundEnvironment.SURFACE : null;
|
||||
}
|
||||
|
||||
private void playSoundForEnvironment(ServerPlayer player, ServerLevel level, float power, SoundEnvironment env, boolean playerInHouse, long baseDelay, boolean isShellingShot, Vec3 eventPos) {
|
||||
boolean useAmbientSound;
|
||||
boolean explosionIsInCaveLocation;
|
||||
double explosionY;
|
||||
double distance = player.m_20182_().m_82554_(eventPos);
|
||||
boolean playerInCave = false;
|
||||
switch (env) {
|
||||
case CAVE: {
|
||||
explosionY = player.m_20186_() + (this.random.m_188500_() - 0.5) * 20.0;
|
||||
explosionIsInCaveLocation = true;
|
||||
playerInCave = true;
|
||||
if (isShellingShot || !((Boolean)Config.COMMON.ambient.soundTypes.enableAmbientCaveDust.get()).booleanValue()) break;
|
||||
PacketHandler.INSTANCE.send(PacketDistributor.PLAYER.with(() -> player), (Object)new SpawnAmbientCaveDustPacket(power));
|
||||
if (this.random.m_188500_() < 0.3 + (double)power * 0.02) {
|
||||
ExplosionOverhaul.addDelayedSound(player, (SoundEvent)ModSounds.DUST_SOUND.get(), SoundSource.AMBIENT, (float)player.m_20185_(), (float)player.m_20186_(), (float)player.m_20189_(), 0.7f, 1.0f, player.m_217043_().m_188505_(), baseDelay + (long)this.random.m_188503_(40));
|
||||
}
|
||||
if (!(this.random.m_188500_() < 0.05 + (double)power * 0.005) || !(power > 15.0f)) break;
|
||||
ExplosionOverhaul.addDelayedSound(player, (SoundEvent)ModSounds.FALLING_STONES_SOUND.get(), SoundSource.AMBIENT, (float)player.m_20185_(), (float)player.m_20186_(), (float)player.m_20189_(), 0.9f, 1.0f, player.m_217043_().m_188505_(), baseDelay + (long)this.random.m_188503_(50));
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
explosionY = eventPos.m_7098_();
|
||||
explosionIsInCaveLocation = false;
|
||||
}
|
||||
}
|
||||
Vec3 finalExplosionPos = new Vec3(eventPos.m_7096_(), explosionY, eventPos.m_7094_());
|
||||
List<SoundEvent> soundPool = ServerExplosionHandler.getSoundPool((Level)level, power, distance, playerInHouse, explosionIsInCaveLocation);
|
||||
if (soundPool == null || soundPool.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
SoundEvent sound = soundPool.get(this.random.m_188503_(soundPool.size()));
|
||||
ResourceLocation soundId = ForgeRegistries.SOUND_EVENTS.getKey((Object)sound);
|
||||
if (soundId == null) {
|
||||
return;
|
||||
}
|
||||
float volume = Math.min(power * 10.0f, 90.0f);
|
||||
float pitch = 0.95f + this.random.m_188501_() * 0.1f;
|
||||
double speedOfSound = 17.15;
|
||||
long delayTicksEffect = baseDelay + (long)(distance / speedOfSound);
|
||||
if (!isShellingShot) {
|
||||
float lampFlickerPowerThreshold;
|
||||
ServerExplosionHandler.CameraShakeProfile shakeProfile = AmbientExplosionManager.determineCameraShakeProfile(power, distance, playerInCave, level);
|
||||
if (shakeProfile.intensity() > 0.0f && shakeProfile.durationTicks() > 0) {
|
||||
int delayTicks = (int)Math.max(0L, Math.round(distance / speedOfSound));
|
||||
PacketHandler.INSTANCE.send(PacketDistributor.PLAYER.with(() -> player), (Object)new CameraShakePacket(shakeProfile.intensity(), shakeProfile.durationTicks(), shakeProfile.pushIntensity(), delayTicks));
|
||||
}
|
||||
if (power >= (lampFlickerPowerThreshold = distance > 1000.0 ? 31.0f : (distance > 500.0 ? 20.0f : (distance > 50.0 ? 10.0f : 4.0f)))) {
|
||||
RedstoneLampEffects.triggerLampFlicker(level, player, power, delayTicksEffect, distance);
|
||||
}
|
||||
}
|
||||
boolean bl = useAmbientSound = env == SoundEnvironment.CAVE;
|
||||
if (useAmbientSound) {
|
||||
ExplosionOverhaul.addDelayedSound(player, sound, SoundSource.AMBIENT, (float)player.m_20185_(), (float)player.m_20186_(), (float)player.m_20189_(), volume, pitch, player.m_217043_().m_188505_(), delayTicksEffect);
|
||||
} else {
|
||||
PacketHandler.INSTANCE.send(PacketDistributor.PLAYER.with(() -> player), (Object)new PlayTrackedSoundPacket(finalExplosionPos, soundId, volume, pitch, delayTicksEffect, playerInHouse));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private record AmbientSoundData(float power, long delay, boolean isShellingShot) {
|
||||
}
|
||||
|
||||
private static enum AmbientEventType {
|
||||
SINGLE,
|
||||
CHAIN_REACTION,
|
||||
SHELLING;
|
||||
|
||||
}
|
||||
|
||||
private static enum SoundEnvironment {
|
||||
SURFACE,
|
||||
CAVE;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,522 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul;
|
||||
|
||||
import com.vinlanx.explosionoverhaul.Config;
|
||||
import com.vinlanx.explosionoverhaul.CraterDeformer;
|
||||
import com.vinlanx.explosionoverhaul.ExplosionOverhaul;
|
||||
import java.lang.invoke.LambdaMetafactory;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.function.Function;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Position;
|
||||
import net.minecraft.core.SectionPos;
|
||||
import net.minecraft.core.Vec3i;
|
||||
import net.minecraft.core.particles.ParticleOptions;
|
||||
import net.minecraft.core.particles.ParticleTypes;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.tags.BlockTags;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.entity.item.FallingBlockEntity;
|
||||
import net.minecraft.world.level.BlockGetter;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||
import net.minecraft.world.level.chunk.LevelChunk;
|
||||
import net.minecraft.world.level.levelgen.Heightmap;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
public class AsyncCraterManager {
|
||||
private static ExecutorService executor;
|
||||
private static final ConcurrentLinkedQueue<Job> activeJobs;
|
||||
private static final AtomicLong globalEpoch;
|
||||
private static final ConcurrentHashMap<ResourceKey<Level>, AtomicLong> dimensionEpochs;
|
||||
|
||||
private static AtomicLong getDimensionEpoch(ResourceKey<Level> dimension) {
|
||||
return dimensionEpochs.computeIfAbsent(dimension, d -> new AtomicLong(0L));
|
||||
}
|
||||
|
||||
private static long incrementDimensionEpoch(ResourceKey<Level> dimension) {
|
||||
return AsyncCraterManager.getDimensionEpoch(dimension).incrementAndGet();
|
||||
}
|
||||
|
||||
public static synchronized void ensureExecutor() {
|
||||
if (executor != null && !executor.isShutdown()) {
|
||||
return;
|
||||
}
|
||||
int configured = (Integer)Config.COMMON.craterMaxThreads.get();
|
||||
int threads = configured == 0 ? Runtime.getRuntime().availableProcessors() : Math.max(1, configured);
|
||||
threads = Math.min(threads, 32);
|
||||
executor = Executors.newFixedThreadPool(threads, r -> {
|
||||
Thread t = new Thread(r, "EO-AsyncCrater");
|
||||
t.setDaemon(true);
|
||||
return t;
|
||||
});
|
||||
}
|
||||
|
||||
public static void submit(ServerLevel level, Vec3 pos, float power) {
|
||||
if (!((Boolean)Config.COMMON.enableCraterDestruction.get()).booleanValue()) {
|
||||
return;
|
||||
}
|
||||
AsyncCraterManager.ensureExecutor();
|
||||
ResourceKey dim = level.m_46472_();
|
||||
Job job = new Job(level, pos, power, globalEpoch.get(), AsyncCraterManager.getDimensionEpoch((ResourceKey<Level>)dim).get());
|
||||
((CompletableFuture)CompletableFuture.runAsync(job::compute, executor).thenRun(() -> {
|
||||
if (!job.isCancelled()) {
|
||||
activeJobs.add(job);
|
||||
}
|
||||
})).exceptionally(throwable -> {
|
||||
ExplosionOverhaul.LOGGER.warn("AsyncCraterManager: failed to compute crater job: {}", (Object)throwable.toString());
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
public static void onServerTick(MinecraftServer server) {
|
||||
Job job;
|
||||
if (activeJobs.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
int size = activeJobs.size();
|
||||
for (int i = 0; i < size && (job = activeJobs.poll()) != null; ++i) {
|
||||
if (job.isCancelled()) continue;
|
||||
job.applyBatch();
|
||||
if (job.isDone()) continue;
|
||||
activeJobs.add(job);
|
||||
}
|
||||
}
|
||||
|
||||
public static void onLevelUnload(ServerLevel level) {
|
||||
if (level == null) {
|
||||
return;
|
||||
}
|
||||
ResourceKey dim = level.m_46472_();
|
||||
AsyncCraterManager.incrementDimensionEpoch((ResourceKey<Level>)dim);
|
||||
activeJobs.removeIf(job -> job.isForDimension((ResourceKey<Level>)dim));
|
||||
}
|
||||
|
||||
public static synchronized void shutdown() {
|
||||
globalEpoch.incrementAndGet();
|
||||
dimensionEpochs.clear();
|
||||
activeJobs.clear();
|
||||
if (executor != null) {
|
||||
executor.shutdownNow();
|
||||
try {
|
||||
executor.awaitTermination(1L, TimeUnit.SECONDS);
|
||||
}
|
||||
catch (InterruptedException interruptedException) {
|
||||
// empty catch block
|
||||
}
|
||||
executor = null;
|
||||
}
|
||||
}
|
||||
|
||||
static {
|
||||
activeJobs = new ConcurrentLinkedQueue();
|
||||
globalEpoch = new AtomicLong(0L);
|
||||
dimensionEpochs = new ConcurrentHashMap();
|
||||
}
|
||||
|
||||
private static class Job {
|
||||
private final Vec3 explosionPos;
|
||||
private final float power;
|
||||
private final ResourceKey<Level> dimensionKey;
|
||||
private final long submitGlobalEpoch;
|
||||
private final long submitDimensionEpoch;
|
||||
private volatile List<Candidate> candidates;
|
||||
private volatile boolean computed;
|
||||
private final ServerLevel levelRef;
|
||||
private int appliedIndex;
|
||||
private final List<Candidate> ordered;
|
||||
private final RandomSource random;
|
||||
private float[] rayEnergy;
|
||||
private boolean[] rayDepleted;
|
||||
private int rayCount;
|
||||
private Set<BlockPos> destroyedPositions = new HashSet<BlockPos>();
|
||||
|
||||
Job(ServerLevel level, Vec3 pos, float power, long submitGlobalEpoch, long submitDimensionEpoch) {
|
||||
this.levelRef = level;
|
||||
this.dimensionKey = level.m_46472_();
|
||||
this.submitGlobalEpoch = submitGlobalEpoch;
|
||||
this.submitDimensionEpoch = submitDimensionEpoch;
|
||||
this.explosionPos = pos;
|
||||
this.power = power;
|
||||
this.candidates = new ArrayList<Candidate>();
|
||||
this.ordered = new ArrayList<Candidate>();
|
||||
this.random = RandomSource.m_216327_();
|
||||
}
|
||||
|
||||
/*
|
||||
* WARNING - Removed try catching itself - possible behaviour change.
|
||||
*/
|
||||
void compute() {
|
||||
try {
|
||||
double multiplier = (Double)Config.COMMON.craterSizeMultiplier.get();
|
||||
double baseRadius = CraterDeformer.calculateRadius(this.power);
|
||||
double finalRadius = baseRadius * multiplier;
|
||||
if (finalRadius <= 0.0) {
|
||||
this.computed = true;
|
||||
return;
|
||||
}
|
||||
boolean large = this.power >= 40.0f;
|
||||
double coreRatio = (Double)Config.COMMON.craterCoreRatio.get();
|
||||
double coreRadius = large ? finalRadius * coreRatio : 0.0;
|
||||
int searchRadius = (int)Math.ceil(finalRadius);
|
||||
BlockPos centerPos = BlockPos.m_274446_((Position)this.explosionPos);
|
||||
RandomSource rnd = RandomSource.m_216327_();
|
||||
if (large) {
|
||||
HashSet<BlockPos> corePositions = new HashSet<BlockPos>();
|
||||
for (int x = -searchRadius; x <= searchRadius; ++x) {
|
||||
for (int y = -searchRadius; y <= searchRadius; ++y) {
|
||||
for (int z = -searchRadius; z <= searchRadius; ++z) {
|
||||
double noise;
|
||||
BlockPos p = centerPos.m_7918_(x, y, z);
|
||||
double dist = Math.sqrt(p.m_123331_((Vec3i)centerPos));
|
||||
if (!(dist <= coreRadius * (noise = 1.0 - rnd.m_188500_() * 0.3)) || !corePositions.add(p)) continue;
|
||||
this.candidates.add(new Candidate(p, -1, 0, true));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
int numberOfRays = (int)Math.max(200.0, Math.min(large ? 25000.0 : 75000.0, finalRadius * (double)(large ? 75 : 150)));
|
||||
double goldenRatio = (1.0 + Math.sqrt(5.0)) / 2.0;
|
||||
double angleIncrement = Math.PI * 2 * goldenRatio;
|
||||
double stepIncrement = 0.4;
|
||||
double startStep = large ? coreRadius * 0.8 : 0.0;
|
||||
this.rayCount = numberOfRays;
|
||||
for (int i = 0; i < numberOfRays; ++i) {
|
||||
double t = (double)i / (double)numberOfRays;
|
||||
double inclination = Math.acos(1.0 - 2.0 * t);
|
||||
double azimuth = angleIncrement * (double)i;
|
||||
Vec3 dir = new Vec3(Math.cos(azimuth) * Math.sin(inclination), Math.sin(azimuth) * Math.sin(inclination), Math.cos(inclination)).m_82541_();
|
||||
int stepIndex = 0;
|
||||
BlockPos lastPos = null;
|
||||
for (double step = startStep; step < finalRadius; step += stepIncrement) {
|
||||
BlockPos p = BlockPos.m_274446_((Position)this.explosionPos.m_82549_(dir.m_82490_(step)));
|
||||
if (p.equals(lastPos)) continue;
|
||||
lastPos = p;
|
||||
this.candidates.add(new Candidate(p, i, stepIndex, false));
|
||||
++stepIndex;
|
||||
}
|
||||
}
|
||||
ArrayList<Candidate> coreBlocks = new ArrayList<Candidate>();
|
||||
ArrayList<Candidate> rayBlocks = new ArrayList<Candidate>();
|
||||
for (Candidate c : this.candidates) {
|
||||
if (c.core) {
|
||||
coreBlocks.add(c);
|
||||
continue;
|
||||
}
|
||||
rayBlocks.add(c);
|
||||
}
|
||||
rayBlocks.sort((a, b) -> {
|
||||
int cmp = Integer.compare(a.rayId, b.rayId);
|
||||
if (cmp != 0) {
|
||||
return cmp;
|
||||
}
|
||||
return Integer.compare(a.stepIndex, b.stepIndex);
|
||||
});
|
||||
this.ordered.addAll(coreBlocks);
|
||||
this.ordered.addAll(rayBlocks);
|
||||
}
|
||||
finally {
|
||||
this.computed = true;
|
||||
}
|
||||
}
|
||||
|
||||
boolean isCancelled() {
|
||||
long currentDimEpoch;
|
||||
if (this.submitGlobalEpoch != globalEpoch.get()) {
|
||||
return true;
|
||||
}
|
||||
AtomicLong dimEpoch = dimensionEpochs.get(this.dimensionKey);
|
||||
long l = currentDimEpoch = dimEpoch == null ? 0L : dimEpoch.get();
|
||||
if (this.submitDimensionEpoch != currentDimEpoch) {
|
||||
return true;
|
||||
}
|
||||
return this.levelRef.m_7654_() == null;
|
||||
}
|
||||
|
||||
boolean isForDimension(ResourceKey<Level> dim) {
|
||||
return this.dimensionKey.equals(dim);
|
||||
}
|
||||
|
||||
boolean isDone() {
|
||||
return this.computed && this.appliedIndex >= this.ordered.size();
|
||||
}
|
||||
|
||||
/*
|
||||
* Unable to fully structure code
|
||||
*/
|
||||
void applyBatch() {
|
||||
block37: {
|
||||
block38: {
|
||||
if (!this.computed) {
|
||||
return;
|
||||
}
|
||||
if (this.isCancelled()) {
|
||||
this.appliedIndex = this.ordered.size();
|
||||
return;
|
||||
}
|
||||
budget = Math.max(100, (Integer)Config.COMMON.craterApplyBlocksPerTick.get());
|
||||
maxFallingPerTick = Math.max(0, (Integer)Config.COMMON.craterMaxFallingBlocksPerTick.get());
|
||||
spawnedFalling = 0;
|
||||
if (this.rayEnergy == null) {
|
||||
multiplier = (Double)Config.COMMON.craterSizeMultiplier.get();
|
||||
large = this.power >= 40.0f;
|
||||
base = (float)((double)(this.power * (large != false ? 4.0f : 7.5f)) * multiplier);
|
||||
this.rayEnergy = new float[Math.max(1, this.rayCount)];
|
||||
this.rayDepleted = new boolean[Math.max(1, this.rayCount)];
|
||||
rnd = this.levelRef.m_213780_();
|
||||
for (i = 0; i < this.rayEnergy.length; ++i) {
|
||||
this.rayEnergy[i] = base * (0.75f + rnd.m_188501_() * 0.5f);
|
||||
}
|
||||
}
|
||||
end = Math.min(this.appliedIndex + budget, this.ordered.size());
|
||||
direct = (Boolean)Config.COMMON.enableDirectChunkWrites.get();
|
||||
if (direct) break block38;
|
||||
while (this.appliedIndex < end) {
|
||||
block39: {
|
||||
block41: {
|
||||
block40: {
|
||||
c = this.ordered.get(this.appliedIndex);
|
||||
pos = c.pos;
|
||||
if (!this.levelRef.m_46749_(pos) || this.levelRef.m_151570_(pos) || !c.core && this.rayDepleted[rayId = Math.max(0, c.rayId)] || this.destroyedPositions.contains(pos) || (state = this.levelRef.m_8055_(pos)).m_60795_()) break block39;
|
||||
if (!((Boolean)Config.COMMON.enableCraterDestruction.get()).booleanValue()) {
|
||||
this.appliedIndex = this.ordered.size();
|
||||
break block37;
|
||||
}
|
||||
resistance = state.m_60800_((BlockGetter)this.levelRef, pos);
|
||||
if (resistance < 0.0f) break block39;
|
||||
if (!ExplosionOverhaul.isBlockStateBlacklisted(state) && !state.m_60734_().m_204297_().m_203656_(BlockTags.f_13070_) && !state.m_60713_(Blocks.f_50722_)) break block40;
|
||||
if (!c.core) {
|
||||
rayId = Math.max(0, c.rayId);
|
||||
this.rayDepleted[rayId] = true;
|
||||
}
|
||||
break block39;
|
||||
}
|
||||
if (!(resistance > Job.calculateMaxResistance(this.power))) break block41;
|
||||
if (!c.core) {
|
||||
rayId = Math.max(0, c.rayId);
|
||||
this.rayDepleted[rayId] = true;
|
||||
}
|
||||
break block39;
|
||||
}
|
||||
if (c.core) ** GOTO lbl-1000
|
||||
v0 = rayId = Math.max(0, c.rayId);
|
||||
this.rayEnergy[v0] = this.rayEnergy[v0] - (resistance + 0.3f);
|
||||
if (this.rayEnergy[rayId] <= 0.0f) {
|
||||
this.rayDepleted[rayId] = true;
|
||||
} else lbl-1000:
|
||||
// 2 sources
|
||||
|
||||
{
|
||||
v1 = allowFalling = this.power <= 20.0f && (Boolean)Config.COMMON.enableFallingBlocks.get() != false && spawnedFalling < maxFallingPerTick;
|
||||
if (allowFalling) {
|
||||
inner = c.core != false || c.stepIndex <= 5;
|
||||
v2 = chance = inner != false ? 0.35 : 0.15;
|
||||
if (this.random.m_188500_() < chance) {
|
||||
falling = FallingBlockEntity.m_201971_((Level)this.levelRef, (BlockPos)pos, (BlockState)state);
|
||||
falling.m_6034_((double)pos.m_123341_() + 0.5, (double)pos.m_123342_() + 0.5, (double)pos.m_123343_() + 0.5);
|
||||
motionDir = Vec3.m_82512_((Vec3i)pos).m_82546_(this.explosionPos).m_82541_();
|
||||
powerMul = 0.4 + this.random.m_188500_() * 0.6;
|
||||
falling.m_20334_(motionDir.f_82479_ * powerMul + (this.random.m_188500_() - 0.5) * 0.3, motionDir.f_82480_ * powerMul + 0.4 + this.random.m_188500_() * 0.3, motionDir.f_82481_ * powerMul + (this.random.m_188500_() - 0.5) * 0.3);
|
||||
++spawnedFalling;
|
||||
}
|
||||
}
|
||||
this.levelRef.m_7731_(pos, Blocks.f_50016_.m_49966_(), 2);
|
||||
this.destroyedPositions.add(pos);
|
||||
}
|
||||
}
|
||||
++this.appliedIndex;
|
||||
}
|
||||
break block37;
|
||||
}
|
||||
maxChunks = Math.max(1, (Integer)Config.COMMON.craterChunksPerTick.get());
|
||||
byChunk = new LinkedHashMap<LevelChunk, List>();
|
||||
i = this.appliedIndex;
|
||||
while (i < end && byChunk.size() < maxChunks) {
|
||||
c = this.ordered.get(i);
|
||||
pos = c.pos;
|
||||
if (!this.levelRef.m_46749_(pos) || this.levelRef.m_151570_(pos)) {
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
chunk = this.levelRef.m_46745_(pos);
|
||||
byChunk.computeIfAbsent(chunk, (Function<LevelChunk, List>)LambdaMetafactory.metafactory(null, null, null, (Ljava/lang/Object;)Ljava/lang/Object;, lambda$applyBatch$1(net.minecraft.world.level.chunk.LevelChunk ), (Lnet/minecraft/world/level/chunk/LevelChunk;)Ljava/util/List;)()).add(c);
|
||||
++i;
|
||||
}
|
||||
for (Map.Entry<K, V> e : byChunk.entrySet()) {
|
||||
chunk = (LevelChunk)e.getKey();
|
||||
list = (List)e.getValue();
|
||||
list.sort((Comparator)LambdaMetafactory.metafactory(null, null, null, (Ljava/lang/Object;Ljava/lang/Object;)I, lambda$applyBatch$2(com.vinlanx.explosionoverhaul.AsyncCraterManager$Job$Candidate com.vinlanx.explosionoverhaul.AsyncCraterManager$Job$Candidate ), (Lcom/vinlanx/explosionoverhaul/AsyncCraterManager$Job$Candidate;Lcom/vinlanx/explosionoverhaul/AsyncCraterManager$Job$Candidate;)I)());
|
||||
modifiedSections = new HashSet<SectionPos>();
|
||||
toRelight = new ArrayList<BlockPos>();
|
||||
relightBudget = Math.min(256, list.size());
|
||||
for (Candidate c : list) {
|
||||
if (!c.core && this.rayDepleted[rayId = Math.max(0, c.rayId)]) {
|
||||
++this.appliedIndex;
|
||||
continue;
|
||||
}
|
||||
pos = c.pos;
|
||||
if (this.destroyedPositions.contains(pos)) {
|
||||
++this.appliedIndex;
|
||||
continue;
|
||||
}
|
||||
if (!((Boolean)Config.COMMON.enableCraterDestruction.get()).booleanValue()) {
|
||||
this.appliedIndex = this.ordered.size();
|
||||
break;
|
||||
}
|
||||
state = this.levelRef.m_8055_(pos);
|
||||
if (state.m_60795_()) {
|
||||
++this.appliedIndex;
|
||||
continue;
|
||||
}
|
||||
resistance = state.m_60800_((BlockGetter)this.levelRef, pos);
|
||||
if (resistance < 0.0f) {
|
||||
++this.appliedIndex;
|
||||
continue;
|
||||
}
|
||||
if (ExplosionOverhaul.isBlockStateBlacklisted(state) || state.m_60734_().m_204297_().m_203656_(BlockTags.f_13070_) || state.m_60713_(Blocks.f_50722_)) {
|
||||
if (!c.core) {
|
||||
rayId = Math.max(0, c.rayId);
|
||||
this.rayDepleted[rayId] = true;
|
||||
}
|
||||
++this.appliedIndex;
|
||||
continue;
|
||||
}
|
||||
if (resistance > Job.calculateMaxResistance(this.power)) {
|
||||
if (!c.core) {
|
||||
rayId = Math.max(0, c.rayId);
|
||||
this.rayDepleted[rayId] = true;
|
||||
}
|
||||
++this.appliedIndex;
|
||||
continue;
|
||||
}
|
||||
if (!c.core) {
|
||||
v3 = rayId = Math.max(0, c.rayId);
|
||||
this.rayEnergy[v3] = this.rayEnergy[v3] - (resistance + 0.3f);
|
||||
if (this.rayEnergy[rayId] <= 0.0f) {
|
||||
this.rayDepleted[rayId] = true;
|
||||
++this.appliedIndex;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (state.m_155947_()) {
|
||||
this.levelRef.m_46961_(pos, true);
|
||||
++this.appliedIndex;
|
||||
continue;
|
||||
}
|
||||
secIdx = chunk.m_151564_(pos.m_123342_());
|
||||
if (secIdx < 0 || secIdx >= chunk.m_7103_().length) {
|
||||
++this.appliedIndex;
|
||||
continue;
|
||||
}
|
||||
section = chunk.m_7103_()[secIdx];
|
||||
old = section.m_62982_(lx = pos.m_123341_() & 15, ly = pos.m_123342_() & 15, lz = pos.m_123343_() & 15);
|
||||
if (old.m_60795_()) {
|
||||
++this.appliedIndex;
|
||||
continue;
|
||||
}
|
||||
section.m_62986_(lx, ly, lz, Blocks.f_50016_.m_49966_());
|
||||
this.destroyedPositions.add(pos);
|
||||
for (Map.Entry m : chunk.m_6890_()) {
|
||||
type = (Heightmap.Types)m.getKey();
|
||||
if (type != Heightmap.Types.MOTION_BLOCKING && type != Heightmap.Types.MOTION_BLOCKING_NO_LEAVES && type != Heightmap.Types.OCEAN_FLOOR && type != Heightmap.Types.WORLD_SURFACE) continue;
|
||||
((Heightmap)m.getValue()).m_64249_(lx, pos.m_123342_(), lz, Blocks.f_50016_.m_49966_());
|
||||
}
|
||||
this.levelRef.m_7260_(pos, old, Blocks.f_50016_.m_49966_(), 2);
|
||||
modifiedSections.add(SectionPos.m_123199_((BlockPos)pos));
|
||||
if (toRelight.size() < relightBudget) {
|
||||
toRelight.add(pos.m_7949_());
|
||||
}
|
||||
v4 = allowFalling = this.power <= 20.0f && (Boolean)Config.COMMON.enableFallingBlocks.get() != false && spawnedFalling < maxFallingPerTick;
|
||||
if (allowFalling) {
|
||||
inner = c.core != false || c.stepIndex <= 5;
|
||||
v5 = chance = inner != false ? 0.35 : 0.15;
|
||||
if (this.random.m_188500_() < chance) {
|
||||
falling = FallingBlockEntity.m_201971_((Level)this.levelRef, (BlockPos)pos, (BlockState)old);
|
||||
falling.m_6034_((double)pos.m_123341_() + 0.5, (double)pos.m_123342_() + 0.5, (double)pos.m_123343_() + 0.5);
|
||||
motionDir = Vec3.m_82512_((Vec3i)pos).m_82546_(this.explosionPos).m_82541_();
|
||||
powerMul = 0.4 + this.random.m_188500_() * 0.6;
|
||||
falling.m_20334_(motionDir.f_82479_ * powerMul + (this.random.m_188500_() - 0.5) * 0.3, motionDir.f_82480_ * powerMul + 0.4 + this.random.m_188500_() * 0.3, motionDir.f_82481_ * powerMul + (this.random.m_188500_() - 0.5) * 0.3);
|
||||
++spawnedFalling;
|
||||
}
|
||||
}
|
||||
++this.appliedIndex;
|
||||
}
|
||||
chunk.m_8092_(true);
|
||||
light = this.levelRef.m_7726_().m_7827_();
|
||||
for (SectionPos sp : modifiedSections) {
|
||||
sec = chunk.m_7103_()[chunk.m_151564_(sp.m_123206_() << 4)];
|
||||
empty = sec.m_188008_();
|
||||
light.m_6191_(sp, empty);
|
||||
}
|
||||
for (BlockPos rp : toRelight) {
|
||||
light.m_7174_(rp);
|
||||
light.m_7174_(rp.m_7494_());
|
||||
}
|
||||
light.m_9353_((ChunkAccess)chunk, true);
|
||||
}
|
||||
}
|
||||
if (this.isDone()) {
|
||||
this.levelRef.m_8767_((ParticleOptions)ParticleTypes.f_123812_, this.explosionPos.f_82479_, this.explosionPos.f_82480_, this.explosionPos.f_82481_, 1, 0.0, 0.0, 0.0, 0.0);
|
||||
}
|
||||
}
|
||||
|
||||
private static float calculateMaxResistance(float power) {
|
||||
float maxRes = power <= 4.0f ? 10.0f : (power <= 10.0f ? 10.0f + (power - 4.0f) * 10.0f / 6.0f : (power <= 25.0f ? 20.0f + (power - 10.0f) * 10.0f / 15.0f : (power <= 40.0f ? 30.0f + (power - 25.0f) * 10.0f / 15.0f : (power <= 70.0f ? 40.0f + (power - 40.0f) * 10.0f / 30.0f : Float.MAX_VALUE))));
|
||||
return maxRes;
|
||||
}
|
||||
|
||||
private static /* synthetic */ int lambda$applyBatch$2(Candidate a, Candidate b) {
|
||||
if (a.core && !b.core) {
|
||||
return -1;
|
||||
}
|
||||
if (!a.core && b.core) {
|
||||
return 1;
|
||||
}
|
||||
if (a.core && b.core) {
|
||||
return 0;
|
||||
}
|
||||
int cmp = Integer.compare(a.rayId, b.rayId);
|
||||
if (cmp != 0) {
|
||||
return cmp;
|
||||
}
|
||||
return Integer.compare(a.stepIndex, b.stepIndex);
|
||||
}
|
||||
|
||||
private static /* synthetic */ List lambda$applyBatch$1(LevelChunk k) {
|
||||
return new ArrayList();
|
||||
}
|
||||
|
||||
private static class Candidate {
|
||||
final BlockPos pos;
|
||||
final int rayId;
|
||||
final int stepIndex;
|
||||
final boolean core;
|
||||
|
||||
Candidate(BlockPos pos, int rayId, int stepIndex, boolean core) {
|
||||
this.pos = pos;
|
||||
this.rayId = rayId;
|
||||
this.stepIndex = stepIndex;
|
||||
this.core = core;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
1804
src/main/java/com/vinlanx/explosionoverhaul/BlockIndexManager.java
Normal file
1804
src/main/java/com/vinlanx/explosionoverhaul/BlockIndexManager.java
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul;
|
||||
|
||||
import com.vinlanx.explosionoverhaul.client.Blur;
|
||||
import java.util.function.Supplier;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.neoforged.api.distmarker.Dist;
|
||||
import net.neoforged.api.distmarker.OnlyIn;
|
||||
import net.neoforged.neoforge.network.NetworkEvent;
|
||||
|
||||
public class BlurTestPacket {
|
||||
private final int durationSeconds;
|
||||
|
||||
public BlurTestPacket(int durationSeconds) {
|
||||
this.durationSeconds = durationSeconds;
|
||||
}
|
||||
|
||||
public static void encode(BlurTestPacket msg, FriendlyByteBuf buf) {
|
||||
buf.writeInt(msg.durationSeconds);
|
||||
}
|
||||
|
||||
public static BlurTestPacket decode(FriendlyByteBuf buf) {
|
||||
return new BlurTestPacket(buf.readInt());
|
||||
}
|
||||
|
||||
public static void handle(BlurTestPacket msg, Supplier<NetworkEvent.Context> ctxSupplier) {
|
||||
NetworkEvent.Context ctx = ctxSupplier.get();
|
||||
ctx.enqueueWork(() -> BlurTestPacket.handleClient(msg));
|
||||
ctx.setPacketHandled(true);
|
||||
}
|
||||
|
||||
@OnlyIn(value=Dist.CLIENT)
|
||||
private static void handleClient(BlurTestPacket msg) {
|
||||
Blur.start(msg.durationSeconds);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul;
|
||||
|
||||
import com.vinlanx.explosionoverhaul.client.CameraShakeConcussionEffect;
|
||||
import java.util.function.Supplier;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.neoforged.api.distmarker.Dist;
|
||||
import net.neoforged.api.distmarker.OnlyIn;
|
||||
import net.neoforged.neoforge.network.NetworkEvent;
|
||||
|
||||
public class CameraShakeConcussionPacket {
|
||||
private final int durationSeconds;
|
||||
private final float intensity;
|
||||
|
||||
public CameraShakeConcussionPacket(int durationSeconds, float intensity) {
|
||||
this.durationSeconds = durationSeconds;
|
||||
this.intensity = intensity;
|
||||
}
|
||||
|
||||
public static void encode(CameraShakeConcussionPacket msg, FriendlyByteBuf buf) {
|
||||
buf.writeInt(msg.durationSeconds);
|
||||
buf.writeFloat(msg.intensity);
|
||||
}
|
||||
|
||||
public static CameraShakeConcussionPacket decode(FriendlyByteBuf buf) {
|
||||
return new CameraShakeConcussionPacket(buf.readInt(), buf.readFloat());
|
||||
}
|
||||
|
||||
public static void handle(CameraShakeConcussionPacket msg, Supplier<NetworkEvent.Context> ctxSupplier) {
|
||||
NetworkEvent.Context ctx = ctxSupplier.get();
|
||||
ctx.enqueueWork(() -> CameraShakeConcussionPacket.handleClient(msg));
|
||||
ctx.setPacketHandled(true);
|
||||
}
|
||||
|
||||
@OnlyIn(value=Dist.CLIENT)
|
||||
private static void handleClient(CameraShakeConcussionPacket msg) {
|
||||
CameraShakeConcussionEffect.start(msg.durationSeconds, msg.intensity);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul;
|
||||
|
||||
import com.vinlanx.explosionoverhaul.client.ClientEffects;
|
||||
import java.util.function.Supplier;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.neoforged.api.distmarker.Dist;
|
||||
import net.neoforged.fml.DistExecutor;
|
||||
import net.neoforged.neoforge.network.NetworkEvent;
|
||||
|
||||
public class CameraShakePacket {
|
||||
private final float intensity;
|
||||
private final int durationTicks;
|
||||
private final float pushIntensity;
|
||||
private final int delayTicks;
|
||||
|
||||
public CameraShakePacket(float intensity, int durationTicks, float pushIntensity, int delayTicks) {
|
||||
this.intensity = intensity;
|
||||
this.durationTicks = durationTicks;
|
||||
this.pushIntensity = pushIntensity;
|
||||
this.delayTicks = delayTicks;
|
||||
}
|
||||
|
||||
public static void encode(CameraShakePacket msg, FriendlyByteBuf buf) {
|
||||
buf.writeFloat(msg.intensity);
|
||||
buf.writeInt(msg.durationTicks);
|
||||
buf.writeFloat(msg.pushIntensity);
|
||||
buf.writeInt(msg.delayTicks);
|
||||
}
|
||||
|
||||
public static CameraShakePacket decode(FriendlyByteBuf buf) {
|
||||
return new CameraShakePacket(buf.readFloat(), buf.readInt(), buf.readFloat(), buf.readInt());
|
||||
}
|
||||
|
||||
public static void handle(CameraShakePacket msg, Supplier<NetworkEvent.Context> ctx) {
|
||||
ctx.get().enqueueWork(() -> DistExecutor.unsafeRunWhenOn((Dist)Dist.CLIENT, () -> () -> ClientEffects.triggerDelayedCameraShake(msg.getIntensity(), msg.getDurationTicks(), msg.getPushIntensity(), msg.getDelayTicks())));
|
||||
ctx.get().setPacketHandled(true);
|
||||
}
|
||||
|
||||
public float getIntensity() {
|
||||
return this.intensity;
|
||||
}
|
||||
|
||||
public int getDurationTicks() {
|
||||
return this.durationTicks;
|
||||
}
|
||||
|
||||
public float getPushIntensity() {
|
||||
return this.pushIntensity;
|
||||
}
|
||||
|
||||
public int getDelayTicks() {
|
||||
return this.delayTicks;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul;
|
||||
|
||||
import net.neoforged.neoforge.client.event.sound.PlaySoundEvent;
|
||||
import net.neoforged.neoforge.event.TickEvent;
|
||||
import net.neoforged.bus.api.EventPriority;
|
||||
import net.neoforged.bus.api.SubscribeEvent;
|
||||
|
||||
public class ClientSoundHandler {
|
||||
private static boolean suppressVanillaExplosionSound = false;
|
||||
private static int suppressionTicksRemaining = 0;
|
||||
|
||||
public static void setSuppressVanillaExplosionSound(boolean suppress, int durationTicks) {
|
||||
suppressVanillaExplosionSound = suppress;
|
||||
suppressionTicksRemaining = durationTicks;
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void onClientTick(TickEvent.ClientTickEvent event) {
|
||||
if (event.phase == TickEvent.Phase.END) {
|
||||
if (suppressionTicksRemaining > 0) {
|
||||
--suppressionTicksRemaining;
|
||||
} else if (suppressionTicksRemaining == 0 && suppressVanillaExplosionSound) {
|
||||
suppressVanillaExplosionSound = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent(priority=EventPriority.HIGH)
|
||||
public void onExplosionSound(PlaySoundEvent event) {
|
||||
if (event.getSound() != null && event.getSound().m_7904_().m_135815_().equals("entity.generic.explode") && suppressVanillaExplosionSound) {
|
||||
event.setSound(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
368
src/main/java/com/vinlanx/explosionoverhaul/Config.java
Normal file
368
src/main/java/com/vinlanx/explosionoverhaul/Config.java
Normal file
@@ -0,0 +1,368 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.LinkOption;
|
||||
import java.nio.file.Path;
|
||||
import net.neoforged.neoforge.common.ForgeConfigSpec;
|
||||
import net.neoforged.fml.loading.FMLPaths;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
public class Config {
|
||||
public static final ForgeConfigSpec CLIENT_SPEC;
|
||||
public static final Client CLIENT;
|
||||
public static final ForgeConfigSpec COMMON_SPEC;
|
||||
public static final Common COMMON;
|
||||
|
||||
public static boolean isFirstLaunch() {
|
||||
if (((Boolean)Config.CLIENT.firstLaunchComplete.get()).booleanValue()) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
Boolean fileVal = Config.readFirstLaunchFromFile();
|
||||
if (fileVal != null && fileVal.booleanValue()) {
|
||||
Config.CLIENT.firstLaunchComplete.set((Object)true);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (Exception exception) {
|
||||
// empty catch block
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void markFirstLaunchComplete() {
|
||||
Config.CLIENT.firstLaunchComplete.set((Object)true);
|
||||
CLIENT_SPEC.save();
|
||||
}
|
||||
|
||||
/*
|
||||
* Enabled aggressive block sorting
|
||||
* Enabled unnecessary exception pruning
|
||||
* Enabled aggressive exception aggregation
|
||||
*/
|
||||
private static Boolean readFirstLaunchFromFile() {
|
||||
Path configPath = FMLPaths.CONFIGDIR.get().resolve("explosionoverhaul").resolve("explosionoverhaul-client.toml");
|
||||
if (!Files.exists(configPath, new LinkOption[0])) {
|
||||
return null;
|
||||
}
|
||||
try (BufferedReader reader = Files.newBufferedReader(configPath);){
|
||||
int eq;
|
||||
String line;
|
||||
String trimmed;
|
||||
do {
|
||||
if ((line = reader.readLine()) == null) return null;
|
||||
} while (!(trimmed = line.trim()).startsWith("firstLaunchComplete") || (eq = trimmed.indexOf(61)) <= 0);
|
||||
String val = trimmed.substring(eq + 1).trim();
|
||||
if (val.startsWith("\"") && val.endsWith("\"")) {
|
||||
val = val.substring(1, val.length() - 1);
|
||||
}
|
||||
Boolean bl = Boolean.parseBoolean(val);
|
||||
return bl;
|
||||
}
|
||||
catch (IOException iOException) {
|
||||
// empty catch block
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static {
|
||||
Pair clientSpecPair = new ForgeConfigSpec.Builder().configure(Client::new);
|
||||
CLIENT_SPEC = (ForgeConfigSpec)clientSpecPair.getRight();
|
||||
CLIENT = (Client)clientSpecPair.getLeft();
|
||||
Pair commonSpecPair = new ForgeConfigSpec.Builder().configure(Common::new);
|
||||
COMMON_SPEC = (ForgeConfigSpec)commonSpecPair.getRight();
|
||||
COMMON = (Common)commonSpecPair.getLeft();
|
||||
}
|
||||
|
||||
public static class Client {
|
||||
public final ForgeConfigSpec.EnumValue<GlowTextureQuality> glowTextureQuality;
|
||||
public final ForgeConfigSpec.EnumValue<ParticleRenderMode> particleRenderMode;
|
||||
public final ForgeConfigSpec.DoubleValue particleSizeScale;
|
||||
public final ForgeConfigSpec.BooleanValue firstLaunchComplete;
|
||||
public final ForgeConfigSpec.BooleanValue enableGroundDustEffect;
|
||||
public final ForgeConfigSpec.DoubleValue groundDustQuality;
|
||||
public final ForgeConfigSpec.IntValue groundDustRaycastFrequency;
|
||||
public final ForgeConfigSpec.BooleanValue enableGroundMistEffect;
|
||||
public final ForgeConfigSpec.DoubleValue groundMistQuality;
|
||||
public final ForgeConfigSpec.IntValue groundMistRaycastFrequency;
|
||||
public final ForgeConfigSpec.BooleanValue enableExplosionParticles;
|
||||
public final ForgeConfigSpec.BooleanValue enablePlasmaParticles;
|
||||
public final ForgeConfigSpec.BooleanValue enablePlasmaSmokeTrail;
|
||||
public final ForgeConfigSpec.DoubleValue plasmaSmokeFrequency;
|
||||
public final ForgeConfigSpec.IntValue plasmaSmokeCount;
|
||||
public final ForgeConfigSpec.BooleanValue enableFlashEffect;
|
||||
public final ForgeConfigSpec.DoubleValue flashMaxOpacity;
|
||||
public final ForgeConfigSpec.BooleanValue enableLineSparks;
|
||||
public final ForgeConfigSpec.DoubleValue lineSparkAmountMultiplier;
|
||||
public final ForgeConfigSpec.BooleanValue enableCameraShake;
|
||||
public final ForgeConfigSpec.DoubleValue cameraShakeAmplifier;
|
||||
public final ForgeConfigSpec.BooleanValue enableShockwaveEffect;
|
||||
public final ForgeConfigSpec.BooleanValue showWindControls;
|
||||
public final ForgeConfigSpec.DoubleValue windVisualizationOpacity;
|
||||
public final ForgeConfigSpec.BooleanValue enableWindEffect;
|
||||
public final ForgeConfigSpec.DoubleValue windSpeedMultiplier;
|
||||
public final ForgeConfigSpec.BooleanValue enableConcussion;
|
||||
public final ForgeConfigSpec.DoubleValue concussionDurationMultiplier;
|
||||
public final ForgeConfigSpec.DoubleValue concussionChanceMultiplier;
|
||||
public final ForgeConfigSpec.BooleanValue enableHeartbeatPulse;
|
||||
public final ForgeConfigSpec.BooleanValue enableCameraSway;
|
||||
public final ForgeConfigSpec.DoubleValue cameraSwayIntensity;
|
||||
public final ForgeConfigSpec.BooleanValue enableDeafness;
|
||||
public final ForgeConfigSpec.BooleanValue enableLowPass;
|
||||
public final ForgeConfigSpec.DoubleValue deafnessChanceMultiplier;
|
||||
public final ForgeConfigSpec.DoubleValue lowPassChanceMultiplier;
|
||||
public final ForgeConfigSpec.BooleanValue showHeartbeatHUD;
|
||||
|
||||
Client(ForgeConfigSpec.Builder builder) {
|
||||
builder.comment("Visual effect settings (client-side only)").push("Render Settings");
|
||||
this.glowTextureQuality = builder.comment(new String[]{"Quality of the main explosion fireball textures (glow, glow_2, sglow).", "Lower quality (64p) can significantly improve performance on systems with less VRAM.", "Requires a resource pack reload (F3+T) to apply the change."}).defineEnum("glowTextureQuality", (Enum)GlowTextureQuality.QUALITY_256);
|
||||
this.particleRenderMode = builder.comment(new String[]{"Particle rendering system mode:", "REALISTIC - Uses animated sprite sheets with complex textures (current system)", "VANILA - Vanilla-like simple textures with color phases (better performance)"}).defineEnum("particleRenderMode", (Enum)ParticleRenderMode.VANILA);
|
||||
this.particleSizeScale = builder.comment(new String[]{"Scales the size of all explosion particles across all render modes.", "1.0 = default size, 0.1 = 10% of default, 5.0 = 500% of default."}).defineInRange("particleSizeScale", 1.0, 0.1, 5.0);
|
||||
this.firstLaunchComplete = builder.comment("Internal flag: marks whether the first-time setup screen has been shown.").define("firstLaunchComplete", false);
|
||||
builder.comment("\nCore explosion visual effects");
|
||||
this.enableExplosionParticles = builder.comment("Enables the main fiery glow particles (glow, glow_2, sglow). Disabling this can significantly improve performance.").define("enableExplosionParticles", true);
|
||||
builder.comment("\nPlasma particle effects");
|
||||
this.enablePlasmaParticles = builder.comment("Enables or disables plasma sparks entirely.").define("enablePlasmaParticles", true);
|
||||
this.enablePlasmaSmokeTrail = builder.comment("Enables the smoke trail that follows plasma sparks.").define("enablePlasmaSmokeTrail", true);
|
||||
this.plasmaSmokeFrequency = builder.comment("Frequency of plasma smoke spawning. 0.0 = no smoke, 0.7 = default chance (70%), 1.0 = always spawn smoke.").defineInRange("plasmaSmokeFrequency", 0.25, 0.0, 1.0);
|
||||
this.plasmaSmokeCount = builder.comment("Number of smoke particles spawned per plasma particle tick. Default was 2.").defineInRange("plasmaSmokeCount", 1, 0, 5);
|
||||
this.enableFlashEffect = builder.comment("Enables the flash overlay effect on explosions.").define("enableFlashEffect", true);
|
||||
this.flashMaxOpacity = builder.comment("Maximum opacity of the flash effect overlay. 0.0 = no flash, 1.0 = full opacity.").defineInRange("flashMaxOpacity", 0.5, 0.0, 1.0);
|
||||
builder.comment("\nConfiguration for the electrical spark effects");
|
||||
this.enableLineSparks = builder.comment("Enables or disables the electrical line sparks that shoot out from explosions.").define("enableLineSparks", true);
|
||||
this.lineSparkAmountMultiplier = builder.comment(new String[]{"Multiplier for the number of sparks generated by an explosion.", "0.0 = no sparks, 1.0 = default amount, 2.0 = double amount.", "Higher values can impact performance."}).defineInRange("lineSparkAmountMultiplier", 1.0, 0.0, 5.0);
|
||||
builder.comment("\nConfiguration for the ground dust cloud effect");
|
||||
this.enableGroundDustEffect = builder.comment("Enables or disables the dust cloud effect from explosions.").define("enableGroundDustEffect", true);
|
||||
this.groundDustQuality = builder.comment(new String[]{"Quality of the dust cloud effect. Affects particle count and duration.", "Lower values can improve performance on weaker PCs.", "0.0 = minimum particles, 1.0 = default quality."}).defineInRange("groundDustQuality", 1.0, 0.0, 1.0);
|
||||
this.groundDustRaycastFrequency = builder.comment(new String[]{"Dust Propagation Quality. Controls how often dust particles check for the ground beneath them.", "A value of 1 means every particle checks (highest quality, high performance cost).", "A value of 10 means every 10th particle checks (default performance)."}).defineInRange("groundDustRaycastFrequency", 10, 1, 20);
|
||||
builder.comment("\nConfiguration for the ground mist effect");
|
||||
this.enableGroundMistEffect = builder.comment("Enables or disables the mist cloud effect from explosions.").define("enableGroundMistEffect", true);
|
||||
this.groundMistQuality = builder.comment(new String[]{"Quality of the mist cloud effect. Affects particle count and duration.", "Lower values can improve performance on weaker PCs.", "0.0 = minimum particles, 1.0 = default quality."}).defineInRange("groundMistQuality", 1.0, 0.0, 1.0);
|
||||
this.groundMistRaycastFrequency = builder.comment(new String[]{"Mist Propagation Quality. Controls how often mist particles check for the ground beneath them.", "A value of 1 means every particle checks (highest quality, high performance cost).", "A value of 10 means every 10th particle checks (default performance)."}).defineInRange("groundMistRaycastFrequency", 10, 1, 20);
|
||||
builder.comment("\nConfiguration for the shockwave effect");
|
||||
this.enableShockwaveEffect = builder.comment("Enables or disables the shockwave particle effect from explosions.").define("enableShockwaveEffect", true);
|
||||
builder.pop();
|
||||
builder.comment("\nCamera shake settings").push("Camera Shake");
|
||||
this.enableCameraShake = builder.comment("Enables or disables the camera shake effect from explosions.").define("enableCameraShake", true);
|
||||
this.cameraShakeAmplifier = builder.comment("Amplifier for the camera shake intensity. 0.0 = no shake, 1.0 = default, 10.0 = maximum shake.").defineInRange("cameraShakeAmplifier", 1.0, 0.0, 10.0);
|
||||
builder.pop();
|
||||
builder.comment("\nWind Effect Settings").push("Wind System");
|
||||
this.enableWindEffect = builder.comment(new String[]{"Enables or disables the wind effect that moves explosion particles (dust and glow).", "When disabled, particles will not be affected by wind and will behave as they originally did."}).define("enableWindEffect", true);
|
||||
this.windSpeedMultiplier = builder.comment(new String[]{"Speed multiplier for the wind effect on particles.", "1.0 = default wind speed, 1.5 = 50% faster, 2.0 = double speed.", "Supports precise values like 1.01, 1.25, 1.75, etc.", "Higher values make particles move faster in the wind direction."}).defineInRange("windSpeedMultiplier", 1.0, 1.0, 2.0);
|
||||
builder.comment("\nWind Visualization").push("Wind Visualization");
|
||||
this.showWindControls = builder.comment(new String[]{"Shows additional wind control information in debug screens or overlays.", "This is a client-only visual setting that doesn't affect gameplay."}).define("showWindControls", false);
|
||||
this.windVisualizationOpacity = builder.comment(new String[]{"Opacity of wind direction visualization effects (if any are implemented).", "0.0 = invisible, 1.0 = fully opaque."}).defineInRange("windVisualizationOpacity", 0.3, 0.0, 1.0);
|
||||
builder.pop();
|
||||
builder.comment("\nConcussion Effect Settings").push("Concussion");
|
||||
this.enableConcussion = builder.comment("Enables or disables the concussion system (blur, deafness, heartbeat, etc.)").define("enableConcussion", true);
|
||||
this.concussionDurationMultiplier = builder.comment("Multiplier for the duration of concussion effects.").defineInRange("concussionDurationMultiplier", 1.0, 0.0, 5.0);
|
||||
this.concussionChanceMultiplier = builder.comment("General chance multiplier for all concussion effects.").defineInRange("concussionChanceMultiplier", 1.0, 0.0, 5.0);
|
||||
this.enableHeartbeatPulse = builder.comment("Enables or disables the visual screen pulse and audio heartbeat (lub-dub).").define("enableHeartbeatPulse", true);
|
||||
this.enableCameraSway = builder.comment("Enables or disables the camera sway (disorientation) effect.").define("enableCameraSway", true);
|
||||
this.cameraSwayIntensity = builder.comment("Intensity (radius) multiplier for camera sway.").defineInRange("cameraSwayIntensity", 1.0, 0.0, 5.0);
|
||||
this.enableDeafness = builder.comment("Enables or disables the high-pitched ringing (deafness) effect.").define("enableDeafness", true);
|
||||
this.enableLowPass = builder.comment("Enables or disables the low-pass (muffled sound) effect.").define("enableLowPass", true);
|
||||
this.deafnessChanceMultiplier = builder.comment("Multiplier for the chance of deafness occurring.").defineInRange("deafnessChanceMultiplier", 1.0, 0.0, 5.0);
|
||||
this.lowPassChanceMultiplier = builder.comment("Multiplier for the chance of low-pass effect occurring.").defineInRange("lowPassChanceMultiplier", 1.0, 0.0, 5.0);
|
||||
this.showHeartbeatHUD = builder.comment("Whether to show the Heartbeat BPM/BPS HUD in the top-right corner.").define("showHeartbeatHUD", false);
|
||||
builder.pop();
|
||||
builder.pop();
|
||||
}
|
||||
|
||||
public static enum GlowTextureQuality {
|
||||
QUALITY_256,
|
||||
QUALITY_64;
|
||||
|
||||
}
|
||||
|
||||
public static enum ParticleRenderMode {
|
||||
REALISTIC,
|
||||
REALISTIC_2,
|
||||
VANILA;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public static class Common {
|
||||
public final ForgeConfigSpec.BooleanValue enablePlayerShake;
|
||||
public final ForgeConfigSpec.DoubleValue playerShakeAmplifier;
|
||||
public final ForgeConfigSpec.BooleanValue enableCraterDestruction;
|
||||
public final ForgeConfigSpec.BooleanValue enableFallingBlocks;
|
||||
public final ForgeConfigSpec.BooleanValue enableExplosionClustering;
|
||||
public final ForgeConfigSpec.IntValue maxClusterPower;
|
||||
public final ForgeConfigSpec.BooleanValue enableGlassBreaking;
|
||||
public final ForgeConfigSpec.BooleanValue enableAsyncCrater;
|
||||
public final ForgeConfigSpec.IntValue craterMaxThreads;
|
||||
public final ForgeConfigSpec.IntValue craterApplyBlocksPerTick;
|
||||
public final ForgeConfigSpec.IntValue craterMaxFallingBlocksPerTick;
|
||||
public final ForgeConfigSpec.BooleanValue enableDirectChunkWrites;
|
||||
public final ForgeConfigSpec.IntValue craterChunksPerTick;
|
||||
public final ForgeConfigSpec.IntValue glassBreakingIntervalTicks;
|
||||
public final ForgeConfigSpec.IntValue glassBlocksPerCycle;
|
||||
public final ForgeConfigSpec.DoubleValue craterSizeMultiplier;
|
||||
public final ForgeConfigSpec.DoubleValue craterCoreRatio;
|
||||
public final ForgeConfigSpec.BooleanValue enableLampFlicker;
|
||||
public final ForgeConfigSpec.IntValue lampFlickerSearchRadius;
|
||||
public final ForgeConfigSpec.BooleanValue enableDripstoneFalling;
|
||||
public final ForgeConfigSpec.IntValue dripstoneFallingSearchRadius;
|
||||
public final ForgeConfigSpec.BooleanValue enableAdvancedSoundSpeed;
|
||||
public final Ambient ambient;
|
||||
public final Scan scan;
|
||||
|
||||
Common(ForgeConfigSpec.Builder builder) {
|
||||
builder.comment("Sound system settings").push("Sounds");
|
||||
this.enableAdvancedSoundSpeed = builder.comment("Enable advanced sound speed system for explosions. If disabled, sound always travels at 343 m/s.").define("enableAdvancedSoundSpeed", false);
|
||||
builder.pop();
|
||||
builder.comment("\nPlayer shake settings").push("Player Shake");
|
||||
this.enablePlayerShake = builder.comment("Enables or disables the player shake effect from explosions.").define("enablePlayerShake", true);
|
||||
this.playerShakeAmplifier = builder.comment("Amplifier for the player shake intensity. 0.0 = no shake, 1.0 = default, 10.0 = maximum shake.").defineInRange("playerShakeAmplifier", 1.0, 0.0, 10.0);
|
||||
builder.pop();
|
||||
builder.comment("Common settings that will be synced from server to client.").push("General");
|
||||
this.enableFallingBlocks = builder.comment(new String[]{"Enables or disables blocks being launched from explosions.", "If false, explosions will still destroy blocks but won't create falling block entities."}).define("enableFallingBlocks", true);
|
||||
this.enableExplosionClustering = builder.comment(new String[]{"Enables or disables the clustering of nearby explosives into a single, more powerful explosion.", "If true, multiple TNT blocks/entities close together will merge into one explosion with increased power."}).define("enableExplosionClustering", true);
|
||||
this.maxClusterPower = builder.comment(new String[]{"Maximum total power for clustered TNT explosions.", "4 = minimum (single TNT), 100 = default, 1000 = extreme (high crash risk).", "WARNING: Values above 150 may cause rendering lag. Values above 500 risk game crashes."}).defineInRange("maxClusterPower", 100, 4, 1000);
|
||||
this.enableDripstoneFalling = builder.comment("Enables or disables the falling effect for pointed dripstone near explosions.").define("enableDripstoneFalling", true);
|
||||
this.enableCraterDestruction = builder.comment(new String[]{"Enables or disables the destruction of blocks, creating craters.", "If false, explosions will still cause visual and sound effects, but won't break blocks."}).define("enableCraterDestruction", true);
|
||||
this.enableGlassBreaking = builder.comment("Enables or disables glass being shattered by the explosion's shockwave.").define("enableGlassBreaking", true);
|
||||
this.enableLampFlicker = builder.comment("Enables or disables the flickering effect on Redstone Lamps near explosions.").define("enableLampFlicker", true);
|
||||
builder.pop();
|
||||
builder.comment("\nDripstone Falling").push("Dripstone Falling");
|
||||
this.dripstoneFallingSearchRadius = builder.comment(new String[]{"The radius around the explosion in which to search for pointed dripstone to fall.", "Warning: High values on servers with many players and dripstones can cause lag."}).defineInRange("dripstoneFallingSearchRadius", 50, 1, 100);
|
||||
builder.pop();
|
||||
builder.comment("\nFine-tuning for the glass breaking effect. High values can impact performance.").push("Glass Breaking");
|
||||
this.glassBreakingIntervalTicks = builder.comment(new String[]{"The interval in game ticks between each glass breaking cycle.", "1 tick = 0.05 seconds. Lower values make the effect smoother but use more server resources.", "Default: 1"}).defineInRange("glassBreakingIntervalTicks", 1, 1, 20);
|
||||
this.glassBlocksPerCycle = builder.comment(new String[]{"The maximum number of glass blocks that can be broken in a single processing cycle.", "This prevents server lag from massive explosions. Higher values can handle large glass structures better but may cause spikes.", "Default: 70"}).defineInRange("glassBlocksPerCycle", 70, 10, 500);
|
||||
builder.pop();
|
||||
builder.comment("\nCrater Customization").push("Crater Settings");
|
||||
this.craterSizeMultiplier = builder.comment(new String[]{"Multiplier for the radius of the explosion crater.", "Affects both crater size and the number of generated particles.", "1.0 = default size."}).defineInRange("craterSizeMultiplier", 1.0, 0.1, 50.0);
|
||||
this.craterCoreRatio = builder.comment(new String[]{"For explosions with power 40+, this controls the shape of the crater.", "Determines the size of the solid 'core' relative to the total radius.", "0.1 = very ray-like, 0.95 = almost a perfect sphere.", "Default: 0.7 (70%)"}).defineInRange("craterCoreRatio", 0.7, 0.1, 0.95);
|
||||
builder.pop();
|
||||
int availableThreadsForCrater = Runtime.getRuntime().availableProcessors();
|
||||
int maxThreadsForSystemCrater = Math.min(32, availableThreadsForCrater);
|
||||
builder.comment("\nAsync crater pipeline (off-thread ray geometry + main-thread batched application)").push("Async Crater");
|
||||
this.enableAsyncCrater = builder.comment(new String[]{"Enable the asynchronous crater pipeline.", "Compute crater geometry off-thread and apply block changes in small batches per tick to keep TPS smooth on large explosions.", "", "WARNING: When asynchronous and multi-threaded mode is enabled - destruction of VS objects - does not work."}).define("enableAsyncCrater", true);
|
||||
this.craterMaxThreads = builder.comment(new String[]{"Maximum number of threads for off-thread crater geometry precomputation.", "0 = Auto (use all available: " + availableThreadsForCrater + ")", "1 = Single-threaded", "2-" + maxThreadsForSystemCrater + " = Custom thread count for this system"}).defineInRange("craterMaxThreads", 0, 0, maxThreadsForSystemCrater);
|
||||
this.craterApplyBlocksPerTick = builder.comment(new String[]{"Maximum number of blocks to evaluate/apply per server tick when building a crater.", "Higher values complete faster but can cause small TPS dips.", "Lower values keep TPS flatter but take longer."}).defineInRange("craterApplyBlocksPerTick", 50000, 0, 150000);
|
||||
this.craterMaxFallingBlocksPerTick = builder.comment(new String[]{"Limit of falling block entities to spawn per tick during crater application (visual debris).", "Set to 0 to disable spawning via the async pipeline."}).defineInRange("craterMaxFallingBlocksPerTick", 500, 0, 2000);
|
||||
this.enableDirectChunkWrites = builder.comment(new String[]{"Directly write block states into chunk sections during crater application (much faster).", "When enabled, bypasses Level#setBlock and updates heightmaps/light manually.", "Note: This skips Forge block events and neighbor updates."}).define("enableDirectChunkWrites", true);
|
||||
this.craterChunksPerTick = builder.comment(new String[]{"Maximum number of chunks to process per tick when direct writes are enabled.", "Used along with block budget to smooth TPS."}).defineInRange("craterChunksPerTick", 120, 0, 500);
|
||||
builder.pop();
|
||||
builder.comment("\nRedstone Lamp Flickering").push("Lamp Flickering");
|
||||
this.lampFlickerSearchRadius = builder.comment(new String[]{"The radius around the player in which to search for lamps to flicker.", "Warning: High values on servers with many players and lamps can cause lag."}).defineInRange("lampFlickerSearchRadius", 50, 1, 100);
|
||||
builder.pop();
|
||||
this.ambient = new Ambient(builder);
|
||||
this.scan = new Scan(builder);
|
||||
}
|
||||
|
||||
public static class Ambient {
|
||||
public final ForgeConfigSpec.BooleanValue enableAmbientExplosions;
|
||||
public final ForgeConfigSpec.IntValue minTimeBetweenExplosions;
|
||||
public final ForgeConfigSpec.IntValue maxTimeBetweenExplosions;
|
||||
public final ForgeConfigSpec.IntValue minExplosionDistance;
|
||||
public final ForgeConfigSpec.IntValue maxExplosionDistance;
|
||||
public final ForgeConfigSpec.DoubleValue maxAmbientExplosionPower;
|
||||
public final Scenarios scenarios;
|
||||
public final PowerTiers powerTiers;
|
||||
public final SoundTypes soundTypes;
|
||||
|
||||
Ambient(ForgeConfigSpec.Builder builder) {
|
||||
builder.comment("Settings for the ambient explosion system, creating a 'battlefield' atmosphere.").push("Ambient");
|
||||
this.enableAmbientExplosions = builder.comment("Globally enables or disables the ambient explosion sound system.").define("enableAmbientExplosions", false);
|
||||
this.minTimeBetweenExplosions = builder.comment("Minimum time in ticks between ambient explosion events (20 ticks = 1 second).").defineInRange("minTimeBetweenExplosions", 1200, 100, 72000);
|
||||
this.maxTimeBetweenExplosions = builder.comment("Maximum time in ticks between ambient explosion events.").defineInRange("maxTimeBetweenExplosions", 6000, 200, 72000);
|
||||
this.minExplosionDistance = builder.comment("Minimum distance in blocks from the player where an ambient sound can originate.").defineInRange("minExplosionDistance", 501, 100, 10000);
|
||||
this.maxExplosionDistance = builder.comment("Maximum distance in blocks from the player where an ambient sound can originate.").defineInRange("maxExplosionDistance", 5001, 200, 10000);
|
||||
this.maxAmbientExplosionPower = builder.comment("The maximum power a random 'Cataclysm' tier explosion can have.").defineInRange("maxAmbientExplosionPower", 80.0, 40.0, 200.0);
|
||||
this.scenarios = new Scenarios(builder);
|
||||
this.powerTiers = new PowerTiers(builder);
|
||||
this.soundTypes = new SoundTypes(builder);
|
||||
builder.pop();
|
||||
}
|
||||
|
||||
public static class Scenarios {
|
||||
public final ForgeConfigSpec.IntValue singleExplosionWeight;
|
||||
public final ForgeConfigSpec.IntValue chainReactionWeight;
|
||||
public final ForgeConfigSpec.IntValue shellingWeight;
|
||||
public final ForgeConfigSpec.IntValue minChainReactionShots;
|
||||
public final ForgeConfigSpec.IntValue maxChainReactionShots;
|
||||
public final ForgeConfigSpec.IntValue minTimeBetweenChainShots;
|
||||
public final ForgeConfigSpec.IntValue maxTimeBetweenChainShots;
|
||||
public final ForgeConfigSpec.IntValue minShellingDelay;
|
||||
public final ForgeConfigSpec.IntValue maxShellingDelay;
|
||||
|
||||
Scenarios(ForgeConfigSpec.Builder builder) {
|
||||
builder.comment(new String[]{"\nConfiguration for different ambient event scenarios.", "The chance for a scenario is (its_weight / sum_of_all_scenario_weights)."}).push("Scenarios");
|
||||
this.singleExplosionWeight = builder.comment("Weight for a standard, single explosion event.").defineInRange("singleExplosionWeight", 70, 0, 1000);
|
||||
this.chainReactionWeight = builder.comment("Weight for a 'Chain Reaction' event (a series of increasingly powerful explosions).").defineInRange("chainReactionWeight", 15, 0, 1000);
|
||||
this.shellingWeight = builder.comment("Weight for an 'Artillery Shelling' event (a quiet shot followed by a delayed, loud impact).").defineInRange("shellingWeight", 15, 0, 1000);
|
||||
builder.comment("\nSettings for the 'Chain Reaction' scenario.").push("ChainReaction");
|
||||
this.minChainReactionShots = builder.defineInRange("minChainReactionShots", 3, 2, 20);
|
||||
this.maxChainReactionShots = builder.defineInRange("maxChainReactionShots", 7, 2, 20);
|
||||
this.minTimeBetweenChainShots = builder.defineInRange("minTimeBetweenChainShots", 10, 5, 200);
|
||||
this.maxTimeBetweenChainShots = builder.defineInRange("maxTimeBetweenChainShots", 40, 10, 400);
|
||||
builder.pop();
|
||||
builder.comment("\nSettings for the 'Artillery Shelling' scenario.").push("Shelling");
|
||||
this.minShellingDelay = builder.comment("Minimum delay in ticks between the 'shot' sound and the 'impact' sound (20 ticks = 1s).").defineInRange("minShellingDelay", 40, 20, 400);
|
||||
this.maxShellingDelay = builder.comment("Maximum delay in ticks between the 'shot' and 'impact' sounds.").defineInRange("maxShellingDelay", 140, 20, 400);
|
||||
builder.pop();
|
||||
builder.pop();
|
||||
}
|
||||
}
|
||||
|
||||
public static class PowerTiers {
|
||||
public final ForgeConfigSpec.IntValue tier1_weight;
|
||||
public final ForgeConfigSpec.IntValue tier2_weight;
|
||||
public final ForgeConfigSpec.IntValue tier3_weight;
|
||||
public final ForgeConfigSpec.IntValue tier4_weight;
|
||||
public final ForgeConfigSpec.IntValue tier5_weight;
|
||||
|
||||
PowerTiers(ForgeConfigSpec.Builder builder) {
|
||||
builder.comment(new String[]{"\nWeighted chances for explosion power tiers (for single and shelling events).", "The chance for a tier is (its_weight / sum_of_all_weights). Set a weight to 0 to disable that tier."}).push("Power_Tiers_Weight");
|
||||
this.tier1_weight = builder.comment("Weight for 'Background Noise' (Power 1-4)").defineInRange("tier1_weight", 50, 0, 1000);
|
||||
this.tier2_weight = builder.comment("Weight for 'Local Skirmish' (Power 5-15)").defineInRange("tier2_weight", 25, 0, 1000);
|
||||
this.tier3_weight = builder.comment("Weight for 'Serious Battle' (Power 16-40)").defineInRange("tier3_weight", 15, 0, 1000);
|
||||
this.tier4_weight = builder.comment("Weight for 'Epicenter' (Power 41-80)").defineInRange("tier4_weight", 8, 0, 1000);
|
||||
this.tier5_weight = builder.comment("Weight for 'Cataclysm' (Power 81+)").defineInRange("tier5_weight", 2, 0, 1000);
|
||||
builder.pop();
|
||||
}
|
||||
}
|
||||
|
||||
public static class SoundTypes {
|
||||
public final ForgeConfigSpec.BooleanValue enableSurfaceSounds;
|
||||
public final ForgeConfigSpec.BooleanValue enableCaveSounds;
|
||||
public final ForgeConfigSpec.BooleanValue enableAmbientCaveDust;
|
||||
|
||||
SoundTypes(ForgeConfigSpec.Builder builder) {
|
||||
builder.comment("\nEnable or disable specific types of ambient sound environments.").push("Sound_Types");
|
||||
this.enableSurfaceSounds = builder.comment("Surface: A clear explosion sound in an open area.").define("enableSurfaceSounds", true);
|
||||
this.enableCaveSounds = builder.comment("Cave: A loud, reverberating sound when both player and explosion are in a cave.").define("enableCaveSounds", true);
|
||||
this.enableAmbientCaveDust = builder.comment("If enabled, an ambient cave explosion will cause a visual dust effect to fall from the ceiling.").define("enableAmbientCaveDust", true);
|
||||
builder.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class Scan {
|
||||
public final ForgeConfigSpec.IntValue maxScanThreads;
|
||||
public final ForgeConfigSpec.IntValue cpuUsagePercent;
|
||||
public final ForgeConfigSpec.BooleanValue enableBlockIndexing;
|
||||
public final ForgeConfigSpec.BooleanValue showScanProgressHUD;
|
||||
|
||||
Scan(ForgeConfigSpec.Builder builder) {
|
||||
int availableThreads = Runtime.getRuntime().availableProcessors();
|
||||
builder.comment(new String[]{"Settings for chunk scanning and block indexing system.", "System detected: " + availableThreads + " CPU threads available", "Configuration ranges are automatically adjusted for your system"}).push("Scan");
|
||||
int maxThreadsForSystem = Math.min(32, availableThreads);
|
||||
this.maxScanThreads = builder.comment(new String[]{"Maximum number of threads to use for chunk scanning.", "Available range for your system: 0-" + maxThreadsForSystem + " threads", "0 = Auto-detect (recommended): uses all " + availableThreads + " available threads", "1 = Single-threaded (slowest but safest)", "2-" + maxThreadsForSystem + " = Custom thread count for this system", "Your system supports up to " + availableThreads + " concurrent threads"}).defineInRange("maxScanThreads", 0, 0, maxThreadsForSystem);
|
||||
this.cpuUsagePercent = builder.comment(new String[]{"How much CPU power to use for chunk scanning (1-100%).", "100% = Maximum speed, uses all available threads intensively", "50% = Balanced, leaves room for other server processes", "25% = Conservative, minimal impact on server performance", "Lower values add delays between chunk processing to reduce CPU load."}).defineInRange("cpuUsagePercent", 75, 1, 100);
|
||||
this.enableBlockIndexing = builder.comment(new String[]{"Enables or disables the block indexing system.", "When enabled, chunks are automatically scanned for Redstone Lamps and Pointed Dripstone.", "When disabled, only manual registration/unregistration of blocks will occur.", "This affects Redstone Lamp flickering and Pointed Dripstone falling effects near explosions."}).define("enableBlockIndexing", true);
|
||||
this.showScanProgressHUD = builder.comment(new String[]{"Controls visibility of the scanning progress HUD.", "When disabled, no progress bar will be shown even if scanning is enabled.", "Shows percentage of chunks scanned during world initialization and automatically hides when complete."}).define("showScanProgressHUD", true);
|
||||
builder.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
244
src/main/java/com/vinlanx/explosionoverhaul/CraterDeformer.java
Normal file
244
src/main/java/com/vinlanx/explosionoverhaul/CraterDeformer.java
Normal file
@@ -0,0 +1,244 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul;
|
||||
|
||||
import com.vinlanx.explosionoverhaul.Config;
|
||||
import com.vinlanx.explosionoverhaul.ExplosionOverhaul;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Position;
|
||||
import net.minecraft.core.Vec3i;
|
||||
import net.minecraft.core.particles.ParticleOptions;
|
||||
import net.minecraft.core.particles.ParticleTypes;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.entity.item.FallingBlockEntity;
|
||||
import net.minecraft.world.level.BlockGetter;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
public class CraterDeformer {
|
||||
public static Set<BlockPos> getCraterBlocks(ServerLevel level, Vec3 explosionPos, float power) {
|
||||
double multiplier = (Double)Config.COMMON.craterSizeMultiplier.get();
|
||||
double baseRadius = CraterDeformer.calculateRadius(power);
|
||||
double finalRadius = baseRadius * multiplier;
|
||||
if (finalRadius <= 0.0) {
|
||||
return new HashSet<BlockPos>();
|
||||
}
|
||||
HashSet<BlockPos> blocksToDestroy = new HashSet<BlockPos>();
|
||||
if (power >= 40.0f) {
|
||||
double coreRatio = (Double)Config.COMMON.craterCoreRatio.get();
|
||||
double coreRadius = finalRadius * coreRatio;
|
||||
int searchRadius = (int)Math.ceil(finalRadius);
|
||||
BlockPos centerPos = BlockPos.m_274446_((Position)explosionPos);
|
||||
RandomSource random = level.m_213780_();
|
||||
for (int x = -searchRadius; x <= searchRadius; ++x) {
|
||||
for (int y = -searchRadius; y <= searchRadius; ++y) {
|
||||
for (int z = -searchRadius; z <= searchRadius; ++z) {
|
||||
double noise;
|
||||
BlockPos currentPos = centerPos.m_7918_(x, y, z);
|
||||
double distanceToCenter = Math.sqrt(currentPos.m_123331_((Vec3i)centerPos));
|
||||
if (!(distanceToCenter <= coreRadius * (noise = 1.0 - random.m_188500_() * 0.3)) || !level.m_46749_(currentPos) || level.m_151570_(currentPos)) continue;
|
||||
BlockState state = level.m_8055_(currentPos);
|
||||
Block block = state.m_60734_();
|
||||
float resistance = state.m_60800_((BlockGetter)level, currentPos);
|
||||
if (state.m_60795_() || resistance < 0.0f || resistance > CraterDeformer.calculateMaxResistance(power) || block == Blocks.f_50722_ || ExplosionOverhaul.isBlockBlacklisted(block)) continue;
|
||||
blocksToDestroy.add(currentPos);
|
||||
}
|
||||
}
|
||||
}
|
||||
int numberOfRays = (int)Math.max(200.0, Math.min(25000.0, finalRadius * 75.0));
|
||||
float rayEnergy = (float)((double)(power * 4.0f) * multiplier);
|
||||
double goldenRatio = (1.0 + Math.sqrt(5.0)) / 2.0;
|
||||
double angleIncrement = Math.PI * 2 * goldenRatio;
|
||||
double stepIncrement = 0.4;
|
||||
block3: for (int i = 0; i < numberOfRays; ++i) {
|
||||
double t = (double)i / (double)numberOfRays;
|
||||
double inclination = Math.acos(1.0 - 2.0 * t);
|
||||
double azimuth = angleIncrement * (double)i;
|
||||
Vec3 rayDirection = new Vec3(Math.cos(azimuth) * Math.sin(inclination), Math.sin(azimuth) * Math.sin(inclination), Math.cos(inclination)).m_82541_();
|
||||
float currentEnergy = rayEnergy * (0.75f + level.m_213780_().m_188501_() * 0.5f);
|
||||
BlockPos lastPos = null;
|
||||
for (double step = coreRadius * 0.8; step < finalRadius; step += 0.4) {
|
||||
BlockPos currentPos = BlockPos.m_274446_((Position)explosionPos.m_82549_(rayDirection.m_82490_(step)));
|
||||
if (currentPos.equals(lastPos) || !level.m_46749_(currentPos) || level.m_151570_(currentPos)) continue;
|
||||
lastPos = currentPos;
|
||||
BlockState state = level.m_8055_(currentPos);
|
||||
Block block = state.m_60734_();
|
||||
if (state.m_60795_() || block == Blocks.f_50722_ || ExplosionOverhaul.isBlockBlacklisted(block)) continue;
|
||||
float resistance = state.m_60800_((BlockGetter)level, currentPos);
|
||||
if (resistance < 0.0f || resistance > CraterDeformer.calculateMaxResistance(power) || block == Blocks.f_50722_ || ExplosionOverhaul.isBlockBlacklisted(block) || !((currentEnergy -= resistance + 0.3f) > 0.0f)) continue block3;
|
||||
blocksToDestroy.add(currentPos);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
int numberOfRays = (int)Math.max(200.0, Math.min(75000.0, finalRadius * 150.0));
|
||||
float rayEnergy = (float)((double)(power * 7.5f) * multiplier);
|
||||
double goldenRatio = (1.0 + Math.sqrt(5.0)) / 2.0;
|
||||
double angleIncrement = Math.PI * 2 * goldenRatio;
|
||||
double stepIncrement = 0.4;
|
||||
RandomSource random = level.m_213780_();
|
||||
block5: for (int i = 0; i < numberOfRays; ++i) {
|
||||
double t = (double)i / (double)numberOfRays;
|
||||
double inclination = Math.acos(1.0 - 2.0 * t);
|
||||
double azimuth = angleIncrement * (double)i;
|
||||
Vec3 rayDirection = new Vec3(Math.cos(azimuth) * Math.sin(inclination), Math.sin(azimuth) * Math.sin(inclination), Math.cos(inclination)).m_82541_();
|
||||
float currentEnergy = rayEnergy * (0.75f + random.m_188501_() * 0.5f);
|
||||
BlockPos lastPos = null;
|
||||
for (double step = 0.0; step < finalRadius; step += 0.4) {
|
||||
BlockPos currentPos = BlockPos.m_274446_((Position)explosionPos.m_82549_(rayDirection.m_82490_(step)));
|
||||
if (currentPos.equals(lastPos) || !level.m_46749_(currentPos) || level.m_151570_(currentPos)) continue;
|
||||
lastPos = currentPos;
|
||||
BlockState state = level.m_8055_(currentPos);
|
||||
Block block = state.m_60734_();
|
||||
if (state.m_60795_() || block == Blocks.f_50722_ || ExplosionOverhaul.isBlockBlacklisted(block)) continue;
|
||||
float resistance = state.m_60800_((BlockGetter)level, currentPos);
|
||||
if (resistance < 0.0f || resistance > CraterDeformer.calculateMaxResistance(power) || block == Blocks.f_50722_ || ExplosionOverhaul.isBlockBlacklisted(block) || !((currentEnergy -= resistance + 0.3f) > 0.0f)) continue block5;
|
||||
blocksToDestroy.add(currentPos);
|
||||
}
|
||||
}
|
||||
}
|
||||
return blocksToDestroy;
|
||||
}
|
||||
|
||||
public static float calculateRadius(float power) {
|
||||
float baseRadius = power <= 4.0f ? Mth.m_14179_((float)(power / 4.0f), (float)2.0f, (float)6.0f) : (power <= 50.0f ? Mth.m_14179_((float)((power - 4.0f) / 46.0f), (float)6.0f, (float)60.0f) : 60.0f + (power - 50.0f) * 1.5f);
|
||||
return baseRadius * 0.5f;
|
||||
}
|
||||
|
||||
private static float calculateMaxResistance(float power) {
|
||||
float maxRes = power <= 4.0f ? 10.0f : (power <= 10.0f ? 10.0f + (power - 4.0f) * 10.0f / 6.0f : (power <= 25.0f ? 20.0f + (power - 10.0f) * 10.0f / 15.0f : (power <= 40.0f ? 30.0f + (power - 25.0f) * 10.0f / 15.0f : (power <= 70.0f ? 40.0f + (power - 40.0f) * 10.0f / 30.0f : Float.MAX_VALUE))));
|
||||
return maxRes;
|
||||
}
|
||||
|
||||
public static void apply(ServerLevel level, Vec3 explosionPos, float power) {
|
||||
if (power >= 40.0f) {
|
||||
CraterDeformer.applyLargeExplosionLogic(level, explosionPos, power);
|
||||
} else {
|
||||
CraterDeformer.applySmallExplosionLogic(level, explosionPos, power);
|
||||
}
|
||||
}
|
||||
|
||||
private static void applyLargeExplosionLogic(ServerLevel level, Vec3 explosionPos, float power) {
|
||||
RandomSource random = level.m_213780_();
|
||||
double multiplier = (Double)Config.COMMON.craterSizeMultiplier.get();
|
||||
double baseRadius = CraterDeformer.calculateRadius(power);
|
||||
double finalRadius = baseRadius * multiplier;
|
||||
if (finalRadius <= 0.0) {
|
||||
return;
|
||||
}
|
||||
HashSet<BlockPos> blocksToDestroy = new HashSet<BlockPos>();
|
||||
HashSet<BlockPos> blocksToLaunch = new HashSet<BlockPos>();
|
||||
double coreRatio = (Double)Config.COMMON.craterCoreRatio.get();
|
||||
double coreRadius = finalRadius * coreRatio;
|
||||
int searchRadius = (int)Math.ceil(finalRadius);
|
||||
BlockPos centerPos = BlockPos.m_274446_((Position)explosionPos);
|
||||
for (int x = -searchRadius; x <= searchRadius; ++x) {
|
||||
for (int y = -searchRadius; y <= searchRadius; ++y) {
|
||||
for (int z = -searchRadius; z <= searchRadius; ++z) {
|
||||
double noise;
|
||||
BlockPos currentPos = centerPos.m_7918_(x, y, z);
|
||||
double distanceToCenter = Math.sqrt(currentPos.m_123331_((Vec3i)centerPos));
|
||||
if (!(distanceToCenter <= coreRadius * (noise = 1.0 - random.m_188500_() * 0.3)) || !level.m_46749_(currentPos) || level.m_151570_(currentPos)) continue;
|
||||
BlockState state = level.m_8055_(currentPos);
|
||||
Block block = state.m_60734_();
|
||||
float resistance = state.m_60800_((BlockGetter)level, currentPos);
|
||||
if (state.m_60795_() || resistance < 0.0f || resistance > CraterDeformer.calculateMaxResistance(power) || block == Blocks.f_50722_ || ExplosionOverhaul.isBlockBlacklisted(block)) continue;
|
||||
blocksToDestroy.add(currentPos);
|
||||
if (!(distanceToCenter < coreRadius * 0.4)) continue;
|
||||
blocksToLaunch.add(currentPos);
|
||||
}
|
||||
}
|
||||
}
|
||||
int numberOfRays = (int)Math.max(200.0, Math.min(25000.0, finalRadius * 75.0));
|
||||
float rayEnergy = (float)((double)(power * 4.0f) * multiplier);
|
||||
double goldenRatio = (1.0 + Math.sqrt(5.0)) / 2.0;
|
||||
double angleIncrement = Math.PI * 2 * goldenRatio;
|
||||
double stepIncrement = 0.4;
|
||||
block3: for (int i = 0; i < numberOfRays; ++i) {
|
||||
double t = (double)i / (double)numberOfRays;
|
||||
double inclination = Math.acos(1.0 - 2.0 * t);
|
||||
double azimuth = angleIncrement * (double)i;
|
||||
Vec3 rayDirection = new Vec3(Math.cos(azimuth) * Math.sin(inclination), Math.sin(azimuth) * Math.sin(inclination), Math.cos(inclination)).m_82541_();
|
||||
float currentEnergy = rayEnergy * (0.75f + random.m_188501_() * 0.5f);
|
||||
BlockPos lastPos = null;
|
||||
for (double step = coreRadius * 0.8; step < finalRadius; step += 0.4) {
|
||||
BlockPos currentPos = BlockPos.m_274446_((Position)explosionPos.m_82549_(rayDirection.m_82490_(step)));
|
||||
if (currentPos.equals(lastPos) || !level.m_46749_(currentPos) || level.m_151570_(currentPos)) continue;
|
||||
lastPos = currentPos;
|
||||
BlockState state = level.m_8055_(currentPos);
|
||||
Block block = state.m_60734_();
|
||||
if (state.m_60795_() || block == Blocks.f_50722_ || ExplosionOverhaul.isBlockBlacklisted(block)) continue;
|
||||
float resistance = state.m_60800_((BlockGetter)level, currentPos);
|
||||
if (resistance < 0.0f || resistance > CraterDeformer.calculateMaxResistance(power) || block == Blocks.f_50722_ || ExplosionOverhaul.isBlockBlacklisted(block) || !((currentEnergy -= resistance + 0.3f) > 0.0f)) continue block3;
|
||||
blocksToDestroy.add(currentPos);
|
||||
}
|
||||
}
|
||||
CraterDeformer.finalizeExplosion(level, explosionPos, power, blocksToDestroy, blocksToLaunch);
|
||||
}
|
||||
|
||||
private static void applySmallExplosionLogic(ServerLevel level, Vec3 explosionPos, float power) {
|
||||
RandomSource random = level.m_213780_();
|
||||
double multiplier = (Double)Config.COMMON.craterSizeMultiplier.get();
|
||||
double baseRadius = CraterDeformer.calculateRadius(power);
|
||||
double finalRadius = baseRadius * multiplier;
|
||||
if (finalRadius <= 0.0) {
|
||||
return;
|
||||
}
|
||||
int numberOfRays = (int)Math.max(200.0, Math.min(75000.0, finalRadius * 150.0));
|
||||
float rayEnergy = (float)((double)(power * 7.5f) * multiplier);
|
||||
HashSet<BlockPos> blocksToDestroy = new HashSet<BlockPos>();
|
||||
HashSet<BlockPos> blocksToLaunch = new HashSet<BlockPos>();
|
||||
double goldenRatio = (1.0 + Math.sqrt(5.0)) / 2.0;
|
||||
double angleIncrement = Math.PI * 2 * goldenRatio;
|
||||
double stepIncrement = 0.4;
|
||||
block0: for (int i = 0; i < numberOfRays; ++i) {
|
||||
double t = (double)i / (double)numberOfRays;
|
||||
double inclination = Math.acos(1.0 - 2.0 * t);
|
||||
double azimuth = angleIncrement * (double)i;
|
||||
Vec3 rayDirection = new Vec3(Math.cos(azimuth) * Math.sin(inclination), Math.sin(azimuth) * Math.sin(inclination), Math.cos(inclination)).m_82541_();
|
||||
float currentEnergy = rayEnergy * (0.75f + random.m_188501_() * 0.5f);
|
||||
BlockPos lastPos = null;
|
||||
for (double step = 0.0; step < finalRadius; step += 0.4) {
|
||||
BlockPos currentPos = BlockPos.m_274446_((Position)explosionPos.m_82549_(rayDirection.m_82490_(step)));
|
||||
if (currentPos.equals(lastPos) || !level.m_46749_(currentPos) || level.m_151570_(currentPos)) continue;
|
||||
lastPos = currentPos;
|
||||
BlockState state = level.m_8055_(currentPos);
|
||||
Block block = state.m_60734_();
|
||||
if (state.m_60795_() || block == Blocks.f_50722_ || ExplosionOverhaul.isBlockBlacklisted(block)) continue;
|
||||
float resistance = state.m_60800_((BlockGetter)level, currentPos);
|
||||
if (resistance < 0.0f || resistance > CraterDeformer.calculateMaxResistance(power) || block == Blocks.f_50722_ || ExplosionOverhaul.isBlockBlacklisted(block) || !((currentEnergy -= resistance + 0.3f) > 0.0f)) continue block0;
|
||||
blocksToDestroy.add(currentPos);
|
||||
if (!(step < finalRadius * 0.3)) continue;
|
||||
blocksToLaunch.add(currentPos);
|
||||
}
|
||||
}
|
||||
CraterDeformer.finalizeExplosion(level, explosionPos, power, blocksToDestroy, blocksToLaunch);
|
||||
}
|
||||
|
||||
private static void finalizeExplosion(ServerLevel level, Vec3 explosionPos, float power, Set<BlockPos> blocksToDestroy, Set<BlockPos> blocksToLaunch) {
|
||||
boolean allowFallingBlocks;
|
||||
RandomSource random = level.m_213780_();
|
||||
level.m_8767_((ParticleOptions)ParticleTypes.f_123812_, explosionPos.f_82479_, explosionPos.f_82480_, explosionPos.f_82481_, 1, 0.0, 0.0, 0.0, 0.0);
|
||||
boolean bl = allowFallingBlocks = power <= 20.0f && (Boolean)Config.COMMON.enableFallingBlocks.get() != false;
|
||||
if (allowFallingBlocks) {
|
||||
for (BlockPos posToLaunch : blocksToLaunch) {
|
||||
if (!(random.m_188500_() < 0.35)) continue;
|
||||
FallingBlockEntity falling = FallingBlockEntity.m_201971_((Level)level, (BlockPos)posToLaunch, (BlockState)level.m_8055_(posToLaunch));
|
||||
falling.m_6034_((double)posToLaunch.m_123341_() + 0.5, (double)posToLaunch.m_123342_() + 0.5, (double)posToLaunch.m_123343_() + 0.5);
|
||||
Vec3 motionDir = Vec3.m_82512_((Vec3i)posToLaunch).m_82546_(explosionPos).m_82541_();
|
||||
double powerMul = 0.5 + random.m_188500_() * 0.8;
|
||||
falling.m_20334_(motionDir.f_82479_ * powerMul + (random.m_188500_() - 0.5) * 0.4, motionDir.f_82480_ * powerMul + 0.5 + random.m_188500_() * 0.4, motionDir.f_82481_ * powerMul + (random.m_188500_() - 0.5) * 0.4);
|
||||
}
|
||||
}
|
||||
for (BlockPos posToDestroy : blocksToDestroy) {
|
||||
level.m_7731_(posToDestroy, Blocks.f_50016_.m_49966_(), 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul;
|
||||
|
||||
import com.mojang.brigadier.StringReader;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import com.mojang.datafixers.kinds.App;
|
||||
import com.mojang.datafixers.kinds.Applicative;
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
import com.vinlanx.explosionoverhaul.ModParticles;
|
||||
import java.util.Locale;
|
||||
import net.minecraft.core.particles.ParticleOptions;
|
||||
import net.minecraft.core.particles.ParticleType;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
|
||||
public class CustomGlowParticleOptions
|
||||
implements ParticleOptions {
|
||||
public static final Codec<CustomGlowParticleOptions> CODEC = RecordCodecBuilder.create(instance -> instance.group((App)Codec.INT.fieldOf("zone").forGetter(CustomGlowParticleOptions::getZone), (App)Codec.FLOAT.fieldOf("power").forGetter(CustomGlowParticleOptions::getPower), (App)Codec.FLOAT.fieldOf("scale").forGetter(CustomGlowParticleOptions::getScale), (App)Codec.INT.fieldOf("animationType").forGetter(CustomGlowParticleOptions::getAnimationType), (App)Codec.FLOAT.fieldOf("centerY").forGetter(CustomGlowParticleOptions::getCenterY), (App)Codec.FLOAT.fieldOf("maxRadius").forGetter(CustomGlowParticleOptions::getMaxRadius), (App)Codec.FLOAT.fieldOf("heightPercent").forGetter(CustomGlowParticleOptions::getHeightPercent)).apply((Applicative)instance, CustomGlowParticleOptions::new));
|
||||
public static final ParticleOptions.Deserializer<CustomGlowParticleOptions> DESERIALIZER = new ParticleOptions.Deserializer<CustomGlowParticleOptions>(){
|
||||
|
||||
public CustomGlowParticleOptions fromCommand(ParticleType<CustomGlowParticleOptions> particleType, StringReader reader) throws CommandSyntaxException {
|
||||
reader.expect(' ');
|
||||
int zone = reader.readInt();
|
||||
reader.expect(' ');
|
||||
float power = reader.readFloat();
|
||||
reader.expect(' ');
|
||||
float scale = reader.readFloat();
|
||||
reader.expect(' ');
|
||||
int animationType = reader.readInt();
|
||||
reader.expect(' ');
|
||||
float centerY = reader.readFloat();
|
||||
reader.expect(' ');
|
||||
float maxRadius = reader.readFloat();
|
||||
reader.expect(' ');
|
||||
float heightPercent = reader.readFloat();
|
||||
return new CustomGlowParticleOptions(zone, power, scale, animationType, centerY, maxRadius, heightPercent);
|
||||
}
|
||||
|
||||
public CustomGlowParticleOptions fromNetwork(ParticleType<CustomGlowParticleOptions> particleType, FriendlyByteBuf buffer) {
|
||||
return new CustomGlowParticleOptions(buffer.readInt(), buffer.readFloat(), buffer.readFloat(), buffer.readInt(), buffer.readFloat(), buffer.readFloat(), buffer.readFloat());
|
||||
}
|
||||
};
|
||||
private final int zone;
|
||||
private final float power;
|
||||
private final float scale;
|
||||
private final int animationType;
|
||||
private final float centerY;
|
||||
private final float maxRadius;
|
||||
private final float heightPercent;
|
||||
|
||||
public CustomGlowParticleOptions(int zone, float power, float scale, int animationType, float centerY, float maxRadius, float heightPercent) {
|
||||
this.zone = zone;
|
||||
this.power = power;
|
||||
this.scale = scale;
|
||||
this.animationType = animationType;
|
||||
this.centerY = centerY;
|
||||
this.maxRadius = maxRadius;
|
||||
this.heightPercent = heightPercent;
|
||||
}
|
||||
|
||||
public CustomGlowParticleOptions(int zone, float power, float scale, int animationType) {
|
||||
this(zone, power, scale, animationType, 0.0f, Math.max(1.0f, power * 2.0f), 0.0f);
|
||||
}
|
||||
|
||||
public CustomGlowParticleOptions(int zone, float power, float scale) {
|
||||
this(zone, power, scale, 0, 0.0f, Math.max(1.0f, power * 2.0f), 0.0f);
|
||||
}
|
||||
|
||||
public ParticleType<?> m_6012_() {
|
||||
return (ParticleType)ModParticles.CUSTOM_GLOW.get();
|
||||
}
|
||||
|
||||
public void m_7711_(FriendlyByteBuf buffer) {
|
||||
buffer.writeInt(this.zone);
|
||||
buffer.writeFloat(this.power);
|
||||
buffer.writeFloat(this.scale);
|
||||
buffer.writeInt(this.animationType);
|
||||
buffer.writeFloat(this.centerY);
|
||||
buffer.writeFloat(this.maxRadius);
|
||||
buffer.writeFloat(this.heightPercent);
|
||||
}
|
||||
|
||||
public String m_5942_() {
|
||||
return String.format(Locale.ROOT, "%s %d %.2f %.2f %d %.2f %.2f %.2f", ModParticles.CUSTOM_GLOW.getId(), this.zone, Float.valueOf(this.power), Float.valueOf(this.scale), this.animationType, Float.valueOf(this.centerY), Float.valueOf(this.maxRadius), Float.valueOf(this.heightPercent));
|
||||
}
|
||||
|
||||
public int getZone() {
|
||||
return this.zone;
|
||||
}
|
||||
|
||||
public float getPower() {
|
||||
return this.power;
|
||||
}
|
||||
|
||||
public float getScale() {
|
||||
return this.scale;
|
||||
}
|
||||
|
||||
public int getAnimationType() {
|
||||
return this.animationType;
|
||||
}
|
||||
|
||||
public float getCenterY() {
|
||||
return this.centerY;
|
||||
}
|
||||
|
||||
public float getMaxRadius() {
|
||||
return this.maxRadius;
|
||||
}
|
||||
|
||||
public float getHeightPercent() {
|
||||
return this.heightPercent;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul;
|
||||
|
||||
import com.vinlanx.explosionoverhaul.BlockIndexManager;
|
||||
import com.vinlanx.explosionoverhaul.Config;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Queue;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.entity.item.FallingBlockEntity;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.PointedDripstoneBlock;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.properties.Property;
|
||||
|
||||
public class DripstoneEffects {
|
||||
private static final Queue<DripstoneFallTask> dripstoneQueue = new ConcurrentLinkedQueue<DripstoneFallTask>();
|
||||
private static final int MAX_DRIPSTONE_TASKS_PER_LEVEL_PER_TICK = 25;
|
||||
|
||||
public static void onServerTick(ServerLevel level) {
|
||||
DripstoneFallTask task;
|
||||
long currentTick = level.m_7654_().m_129921_();
|
||||
int processedTasks = 0;
|
||||
while (processedTasks < 25 && (task = dripstoneQueue.peek()) != null) {
|
||||
Comparable thicknessVal;
|
||||
if (task.level != level) {
|
||||
dripstoneQueue.poll();
|
||||
dripstoneQueue.add(task);
|
||||
++processedTasks;
|
||||
continue;
|
||||
}
|
||||
if (task.triggerTick > currentTick) break;
|
||||
dripstoneQueue.poll();
|
||||
++processedTasks;
|
||||
BlockState state = level.m_8055_(task.pos);
|
||||
if (!state.m_60713_(Blocks.f_152588_) || !state.m_61138_((Property)PointedDripstoneBlock.f_154010_) || (thicknessVal = state.m_61143_((Property)PointedDripstoneBlock.f_154010_)) == null || !"tip".equalsIgnoreCase(String.valueOf(thicknessVal))) continue;
|
||||
FallingBlockEntity falling = FallingBlockEntity.m_201971_((Level)level, (BlockPos)task.pos, (BlockState)state);
|
||||
if (falling != null) {
|
||||
// empty if block
|
||||
}
|
||||
level.m_7731_(task.pos, Blocks.f_50016_.m_49966_(), 2);
|
||||
}
|
||||
}
|
||||
|
||||
public static void handleDripstoneFall(ServerLevel level, BlockPos center, int explosionPower, RandomSource random) {
|
||||
int radius = (Integer)Config.COMMON.dripstoneFallingSearchRadius.get();
|
||||
List<BlockPos> dripstones = BlockIndexManager.getNearby(level, center, radius, BlockIndexManager.BlockType.DRIPSTONE);
|
||||
if (dripstones.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
int sampleLimit = 8;
|
||||
boolean anyPresent = false;
|
||||
for (int i = 0; i < Math.min(sampleLimit, dripstones.size()); ++i) {
|
||||
BlockState s;
|
||||
BlockPos p = dripstones.get(i);
|
||||
if (!level.m_46749_(p) || !(s = level.m_8055_(p)).m_60713_(Blocks.f_152588_)) continue;
|
||||
anyPresent = true;
|
||||
break;
|
||||
}
|
||||
if (!anyPresent) {
|
||||
return;
|
||||
}
|
||||
int percent = DripstoneEffects.getFallPercent(explosionPower);
|
||||
int toFall = dripstones.size() * percent / 100;
|
||||
int maxFall = 200;
|
||||
Collections.shuffle(dripstones, new Random(random.m_188505_()));
|
||||
List<BlockPos> selected = dripstones.subList(0, Math.min(Math.min(toFall, dripstones.size()), maxFall));
|
||||
long currentTick = level.m_7654_().m_129921_();
|
||||
for (BlockPos pos : selected) {
|
||||
int delayTicks = 5 + random.m_188503_(16);
|
||||
dripstoneQueue.add(new DripstoneFallTask(level, pos, currentTick + (long)delayTicks));
|
||||
}
|
||||
}
|
||||
|
||||
private static int getFallPercent(int power) {
|
||||
if (power < 10) {
|
||||
return 0;
|
||||
}
|
||||
if (power < 20) {
|
||||
return 40;
|
||||
}
|
||||
if (power < 30) {
|
||||
return 50;
|
||||
}
|
||||
if (power < 40) {
|
||||
return 60;
|
||||
}
|
||||
if (power < 50) {
|
||||
return 70;
|
||||
}
|
||||
if (power < 60) {
|
||||
return 80;
|
||||
}
|
||||
if (power < 70) {
|
||||
return 90;
|
||||
}
|
||||
return 100;
|
||||
}
|
||||
|
||||
private static List<BlockPos> findDripstones(ServerLevel level, BlockPos center, int radius) {
|
||||
return BlockIndexManager.getNearby(level, center, radius, BlockIndexManager.BlockType.DRIPSTONE);
|
||||
}
|
||||
|
||||
private static class DripstoneFallTask {
|
||||
public final ServerLevel level;
|
||||
public final BlockPos pos;
|
||||
public final long triggerTick;
|
||||
|
||||
public DripstoneFallTask(ServerLevel level, BlockPos pos, long triggerTick) {
|
||||
this.level = level;
|
||||
this.pos = pos;
|
||||
this.triggerTick = triggerTick;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul;
|
||||
|
||||
import com.vinlanx.explosionoverhaul.Config;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Position;
|
||||
import net.minecraft.core.Vec3i;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.entity.item.PrimedTnt;
|
||||
import net.minecraft.world.entity.monster.Creeper;
|
||||
import net.minecraft.world.entity.vehicle.AbstractMinecart;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
public class ExplosionClusterHandler {
|
||||
public static float calculateClusteredPower(Level level, Vec3 explosionPos, float initialPower) {
|
||||
if (!((Boolean)Config.COMMON.enableExplosionClustering.get()).booleanValue()) {
|
||||
return initialPower;
|
||||
}
|
||||
double searchRadius = ExplosionClusterHandler.getSearchRadius(initialPower);
|
||||
AABB searchBox = new AABB(explosionPos.f_82479_ - searchRadius, explosionPos.f_82480_ - searchRadius, explosionPos.f_82481_ - searchRadius, explosionPos.f_82479_ + searchRadius, explosionPos.f_82480_ + searchRadius, explosionPos.f_82481_ + searchRadius);
|
||||
List tntEntities = level.m_45976_(PrimedTnt.class, searchBox);
|
||||
List creepers = level.m_45976_(Creeper.class, searchBox);
|
||||
List minecarts = level.m_45976_(AbstractMinecart.class, searchBox);
|
||||
ArrayList<BlockPos> tntBlocks = new ArrayList<BlockPos>();
|
||||
BlockPos centerPos = BlockPos.m_274446_((Position)explosionPos);
|
||||
int radiusBlocks = (int)Math.ceil(searchRadius);
|
||||
for (int x = -radiusBlocks; x <= radiusBlocks; ++x) {
|
||||
for (int y = -radiusBlocks; y <= radiusBlocks; ++y) {
|
||||
for (int z = -radiusBlocks; z <= radiusBlocks; ++z) {
|
||||
BlockPos pos = centerPos.m_7918_(x, y, z);
|
||||
BlockState state = level.m_8055_(pos);
|
||||
if (state.m_60734_() != Blocks.f_50077_) continue;
|
||||
tntBlocks.add(pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
boolean hasTntMinecart = minecarts.stream().anyMatch(c -> c.m_6095_() == EntityType.f_20475_);
|
||||
if (tntEntities.isEmpty() && tntBlocks.isEmpty() && creepers.isEmpty() && !hasTntMinecart) {
|
||||
return initialPower;
|
||||
}
|
||||
ArrayList<ExplosionSource> sources = new ArrayList<ExplosionSource>();
|
||||
sources.add(new ExplosionSource(explosionPos, initialPower));
|
||||
for (PrimedTnt tnt : tntEntities) {
|
||||
if (tnt.m_20182_().equals((Object)explosionPos)) continue;
|
||||
sources.add(new ExplosionSource(tnt.m_20182_(), 4.0f));
|
||||
}
|
||||
for (Creeper creeper : creepers) {
|
||||
if (creeper.m_20182_().equals((Object)explosionPos)) continue;
|
||||
sources.add(new ExplosionSource(creeper.m_20182_(), 3.0f));
|
||||
}
|
||||
for (AbstractMinecart cart : minecarts) {
|
||||
if (cart.m_6095_() != EntityType.f_20475_ || cart.m_20182_().equals((Object)explosionPos)) continue;
|
||||
sources.add(new ExplosionSource(cart.m_20182_(), 4.0f));
|
||||
}
|
||||
for (BlockPos pos : tntBlocks) {
|
||||
Vec3 blockPos = Vec3.m_82512_((Vec3i)pos);
|
||||
if (blockPos.equals((Object)explosionPos)) continue;
|
||||
sources.add(new ExplosionSource(blockPos, 4.0f));
|
||||
}
|
||||
ExplosionSource mainSource = sources.stream().max((a, b) -> Float.compare(a.power, b.power)).orElse((ExplosionSource)sources.get(0));
|
||||
float totalPower = mainSource.power;
|
||||
for (ExplosionSource source : sources) {
|
||||
if (source == mainSource) continue;
|
||||
float addition = ExplosionClusterHandler.getPowerAddition(source.power);
|
||||
totalPower += addition;
|
||||
}
|
||||
for (PrimedTnt tnt : tntEntities) {
|
||||
if (tnt.m_20182_().equals((Object)explosionPos)) continue;
|
||||
tnt.m_146870_();
|
||||
}
|
||||
for (Creeper creeper : creepers) {
|
||||
if (creeper.m_20182_().equals((Object)explosionPos)) continue;
|
||||
creeper.m_146870_();
|
||||
}
|
||||
for (AbstractMinecart cart : minecarts) {
|
||||
if (cart.m_6095_() != EntityType.f_20475_ || cart.m_20182_().equals((Object)explosionPos)) continue;
|
||||
cart.m_146870_();
|
||||
}
|
||||
for (BlockPos pos : tntBlocks) {
|
||||
Vec3 blockPos = Vec3.m_82512_((Vec3i)pos);
|
||||
if (blockPos.equals((Object)explosionPos)) continue;
|
||||
level.m_7731_(pos, Blocks.f_50016_.m_49966_(), 3);
|
||||
}
|
||||
float maxPower = ((Integer)Config.COMMON.maxClusterPower.get()).floatValue();
|
||||
return Math.min(totalPower, maxPower);
|
||||
}
|
||||
|
||||
private static double getSearchRadius(float power) {
|
||||
if (power <= 4.0f) {
|
||||
return 3.0;
|
||||
}
|
||||
if (power <= 10.0f) {
|
||||
return 5.0;
|
||||
}
|
||||
if (power <= 25.0f) {
|
||||
return 10.0;
|
||||
}
|
||||
if (power <= 35.0f) {
|
||||
return 14.0;
|
||||
}
|
||||
return 20.0;
|
||||
}
|
||||
|
||||
private static float getPowerAddition(float power) {
|
||||
if (power <= 4.0f) {
|
||||
return 2.0f;
|
||||
}
|
||||
if (power <= 10.0f) {
|
||||
return 5.0f;
|
||||
}
|
||||
if (power <= 25.0f) {
|
||||
return 10.0f;
|
||||
}
|
||||
if (power <= 35.0f) {
|
||||
return 15.0f;
|
||||
}
|
||||
return 15.0f;
|
||||
}
|
||||
|
||||
private static class ExplosionSource {
|
||||
Vec3 position;
|
||||
float power;
|
||||
|
||||
ExplosionSource(Vec3 position, float power) {
|
||||
this.position = position;
|
||||
this.power = power;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,681 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
|
||||
import com.mojang.logging.LogUtils;
|
||||
import com.vinlanx.explosionoverhaul.AmbientExplosionManager;
|
||||
import com.vinlanx.explosionoverhaul.AsyncCraterManager;
|
||||
import com.vinlanx.explosionoverhaul.BlockIndexManager;
|
||||
import com.vinlanx.explosionoverhaul.ClientSoundHandler;
|
||||
import com.vinlanx.explosionoverhaul.Config;
|
||||
import com.vinlanx.explosionoverhaul.CustomGlowParticleOptions;
|
||||
import com.vinlanx.explosionoverhaul.DripstoneEffects;
|
||||
import com.vinlanx.explosionoverhaul.GlassBreakingEffects;
|
||||
import com.vinlanx.explosionoverhaul.ModBlockEntities;
|
||||
import com.vinlanx.explosionoverhaul.ModBlocks;
|
||||
import com.vinlanx.explosionoverhaul.ModCreativeTabs;
|
||||
import com.vinlanx.explosionoverhaul.ModItems;
|
||||
import com.vinlanx.explosionoverhaul.ModParticles;
|
||||
import com.vinlanx.explosionoverhaul.ModSounds;
|
||||
import com.vinlanx.explosionoverhaul.PacketHandler;
|
||||
import com.vinlanx.explosionoverhaul.PlasmaParticleOptions;
|
||||
import com.vinlanx.explosionoverhaul.RedstoneLampEffects;
|
||||
import com.vinlanx.explosionoverhaul.ScanInfoHUD;
|
||||
import com.vinlanx.explosionoverhaul.ScanKeyHandler;
|
||||
import com.vinlanx.explosionoverhaul.ScanLoadInfoHUD;
|
||||
import com.vinlanx.explosionoverhaul.ScanLoadPromptHUD;
|
||||
import com.vinlanx.explosionoverhaul.ScanProgressHUD;
|
||||
import com.vinlanx.explosionoverhaul.ScanPromptHUD;
|
||||
import com.vinlanx.explosionoverhaul.ServerExplosionHandler;
|
||||
import com.vinlanx.explosionoverhaul.VinlanxTheLightRenderer;
|
||||
import com.vinlanx.explosionoverhaul.client.Blur;
|
||||
import com.vinlanx.explosionoverhaul.client.ClientEffects;
|
||||
import com.vinlanx.explosionoverhaul.client.ConcussionAudioEffect;
|
||||
import com.vinlanx.explosionoverhaul.client.CustomGlowParticleProvider;
|
||||
import com.vinlanx.explosionoverhaul.client.ExplosionTextureManager;
|
||||
import com.vinlanx.explosionoverhaul.client.ExplosionWindController;
|
||||
import com.vinlanx.explosionoverhaul.client.FirstTimeSetupHandler;
|
||||
import com.vinlanx.explosionoverhaul.client.IntroMusicTickHandler;
|
||||
import com.vinlanx.explosionoverhaul.client.LineSparkParticleProvider;
|
||||
import com.vinlanx.explosionoverhaul.client.ModConfigScreen;
|
||||
import com.vinlanx.explosionoverhaul.client.ModKeyMappings;
|
||||
import com.vinlanx.explosionoverhaul.client.PlasmaParticle;
|
||||
import com.vinlanx.explosionoverhaul.client.SmokeParticle;
|
||||
import com.vinlanx.explosionoverhaul.client.SoundPhysicsCompatibility;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.nio.file.CopyOption;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.LinkOption;
|
||||
import java.nio.file.OpenOption;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
import java.nio.file.attribute.FileAttribute;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.Executor;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.client.renderer.ShaderInstance;
|
||||
import net.minecraft.client.renderer.texture.TextureManager;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.particles.BlockParticleOption;
|
||||
import net.minecraft.core.particles.ParticleOptions;
|
||||
import net.minecraft.core.particles.ParticleType;
|
||||
import net.minecraft.core.particles.ParticleTypes;
|
||||
import net.minecraft.network.protocol.Packet;
|
||||
import net.minecraft.network.protocol.game.ClientboundSoundPacket;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.server.packs.resources.PreparableReloadListener;
|
||||
import net.minecraft.server.packs.resources.ResourceManager;
|
||||
import net.minecraft.sounds.SoundEvent;
|
||||
import net.minecraft.sounds.SoundSource;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.util.profiling.ProfilerFiller;
|
||||
import net.minecraft.world.level.LevelAccessor;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.neoforged.api.distmarker.Dist;
|
||||
import net.neoforged.neoforge.client.ConfigScreenHandler;
|
||||
import net.neoforged.neoforge.client.event.ClientPlayerNetworkEvent;
|
||||
import net.neoforged.neoforge.client.event.EntityRenderersEvent;
|
||||
import net.neoforged.neoforge.client.event.RegisterClientReloadListenersEvent;
|
||||
import net.neoforged.neoforge.client.event.RegisterKeyMappingsEvent;
|
||||
import net.neoforged.neoforge.client.event.RegisterParticleProvidersEvent;
|
||||
import net.neoforged.neoforge.client.event.RegisterShadersEvent;
|
||||
import net.neoforged.neoforge.client.event.RenderGuiOverlayEvent;
|
||||
import net.neoforged.neoforge.common.MinecraftForge;
|
||||
import net.neoforged.neoforge.event.TickEvent;
|
||||
import net.neoforged.neoforge.event.entity.player.PlayerEvent;
|
||||
import net.neoforged.neoforge.event.level.LevelEvent;
|
||||
import net.neoforged.neoforge.event.server.ServerStoppedEvent;
|
||||
import net.neoforged.bus.api.IEventBus;
|
||||
import net.neoforged.bus.api.SubscribeEvent;
|
||||
import net.neoforged.fml.DistExecutor;
|
||||
import net.neoforged.fml.ModLoadingContext;
|
||||
import net.neoforged.fml.common.Mod;
|
||||
import net.neoforged.fml.config.IConfigSpec;
|
||||
import net.neoforged.fml.config.ModConfig;
|
||||
import net.neoforged.fml.event.lifecycle.FMLClientSetupEvent;
|
||||
import net.neoforged.fml.event.lifecycle.FMLCommonSetupEvent;
|
||||
import net.neoforged.fml.javafmlmod.FMLJavaModLoadingContext;
|
||||
import net.neoforged.neoforge.registries.ForgeRegistries;
|
||||
import net.neoforged.neoforge.server.ServerLifecycleHooks;
|
||||
import org.slf4j.Logger;
|
||||
import software.bernie.geckolib.GeckoLib;
|
||||
|
||||
@Mod(value="explosionoverhaul")
|
||||
public class ExplosionOverhaul {
|
||||
public static final String MODID = "explosionoverhaul";
|
||||
public static final Logger LOGGER = LogUtils.getLogger();
|
||||
private static final Map<String, ExplosionSourceMode> SOURCE_MODES = new HashMap<String, ExplosionSourceMode>();
|
||||
private static final List<String> EXPLOSION_BLACKLIST = new ArrayList<String>();
|
||||
private static final List<String> DEFAULT_BLACKLIST = List.of("ancient_elements:block_of_raw_infernal_ore", "ancient_elements:celestium_ore", "ancient_elements:deepslate_frost_ore", "ancient_elements:deepslate_jungle_steel_ore", "ancient_elements:deepslate_lead_ore", "ancient_elements:deepslate_steel_ore", "ancient_elements:deepslate_tin_ore", "ancient_elements:deepslate_titanium_ore", "ancient_elements:ender_steel_ore", "ancient_elements:endrium_ore", "ancient_elements:frost_ore", "ancient_elements:infernal_ore", "ancient_elements:jungle_steel_ore", "ancient_elements:lead_ore", "ancient_elements:meteorite_ore", "ancient_elements:nether_steel_ore", "ancient_elements:palladium_ore", "ancient_elements:spectrillium_ore", "ancient_elements:steel_ore", "ancient_elements:tin_ore", "ancient_elements:titanium_ore", "ancient_elements:void_steel_ore", "mofus_better_end_:void_portal_block", "mofus_better_end_:void_portal_igniter", "mofus_better_end_:star_portal");
|
||||
private static final Path CONFIG_DIR = Paths.get("config", "explosionoverhaul");
|
||||
private static final Path OLD_COMMON = Paths.get("config", "explosionoverhaul-common.toml");
|
||||
private static final Path OLD_CLIENT = Paths.get("config", "explosionoverhaul-client.toml");
|
||||
private static final Path NEW_COMMON = CONFIG_DIR.resolve("explosionoverhaul-common.toml");
|
||||
private static final Path NEW_CLIENT = CONFIG_DIR.resolve("explosionoverhaul-client.toml");
|
||||
private static final Path BLACKLIST_JSON = CONFIG_DIR.resolve("DestroyingBlacklist.json");
|
||||
private static final Path SOURCE_MODES_JSON = CONFIG_DIR.resolve("ExplosionSourceBlacklist.json");
|
||||
private static final List<DelayedSound> delayedSounds = Collections.synchronizedList(new ArrayList());
|
||||
private static final List<DelayedParticle> delayedParticles = Collections.synchronizedList(new ArrayList());
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onServerTick(TickEvent.LevelTickEvent event) {
|
||||
}
|
||||
|
||||
private static void ensureConfigDirectory() {
|
||||
try {
|
||||
Files.createDirectories(CONFIG_DIR, new FileAttribute[0]);
|
||||
ExplosionOverhaul.writeConfigReadme();
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOGGER.warn("Failed to create config/explosionoverhaul directory", (Throwable)e);
|
||||
}
|
||||
}
|
||||
|
||||
private static void writeConfigReadme() {
|
||||
Path readmePath = CONFIG_DIR.resolve("README.md");
|
||||
if (Files.exists(readmePath, new LinkOption[0])) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
String content = "# Explosion Overhaul Config Helpers\n\n## Blacklist Files (.json)\n\n### DestroyingBlacklist.json\n- **Format**: `[\"namespace:block_id\", ...]`\n- **Effect**: Blocks listed here are immune to explosion craters.\n\n### GlassBlacklist.json\n- **Format**: `[\"namespace:block_id\", ...]`\n- **Effect**: Blocks listed here won't be shattered by the glass-breaking system.\n\n### ExplosionSourceBlacklist.json\n- **Format**: `{\"namespace:entity_id\": \"MODE\"}`\n- **Modes**:\n - `DEFAULT`: Standard mod behavior (crater + concussion + sounds).\n - `VANILLA`: Reverts to vanilla explosion logic for this source.\n - `NO_DESTRUCTION`: Concussions and sounds only (no crater or glass breaking).\n - `NO_DESTRUCTION_GLASSWORKS`: Like NO_DESTRUCTION, but glass still shatters.\n\n**Note**: Invalid JSON (extra commas, comments) will cause the mod to use defaults. Restart the game/server for changes to take effect.\n\nhttps://www.youtube.com/watch?v=dQw4w9WgXcQ";
|
||||
Files.writeString(readmePath, (CharSequence)content, new OpenOption[0]);
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOGGER.warn("Failed to write config README.md", (Throwable)e);
|
||||
}
|
||||
}
|
||||
|
||||
private static void migrateOldTomlIfPresent() {
|
||||
try {
|
||||
byte[] oldBytes;
|
||||
if (Files.exists(OLD_COMMON, new LinkOption[0])) {
|
||||
ExplosionOverhaul.ensureConfigDirectory();
|
||||
if (!Files.exists(NEW_COMMON, new LinkOption[0])) {
|
||||
Files.move(OLD_COMMON, NEW_COMMON, new CopyOption[0]);
|
||||
} else {
|
||||
oldBytes = Files.readAllBytes(OLD_COMMON);
|
||||
Files.write(NEW_COMMON, oldBytes, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.CREATE);
|
||||
Files.delete(OLD_COMMON);
|
||||
}
|
||||
}
|
||||
if (Files.exists(OLD_CLIENT, new LinkOption[0])) {
|
||||
ExplosionOverhaul.ensureConfigDirectory();
|
||||
if (!Files.exists(NEW_CLIENT, new LinkOption[0])) {
|
||||
Files.move(OLD_CLIENT, NEW_CLIENT, new CopyOption[0]);
|
||||
} else {
|
||||
oldBytes = Files.readAllBytes(OLD_CLIENT);
|
||||
Files.write(NEW_CLIENT, oldBytes, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.CREATE);
|
||||
Files.delete(OLD_CLIENT);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOGGER.warn("Failed to migrate old toml configs", (Throwable)e);
|
||||
}
|
||||
}
|
||||
|
||||
private static void loadBlacklistFromJson() {
|
||||
ExplosionOverhaul.ensureConfigDirectory();
|
||||
Gson gson = new GsonBuilder().setPrettyPrinting().create();
|
||||
try {
|
||||
if (!Files.exists(BLACKLIST_JSON, new LinkOption[0])) {
|
||||
try (BufferedWriter w = Files.newBufferedWriter(BLACKLIST_JSON, new OpenOption[0]);){
|
||||
gson.toJson(DEFAULT_BLACKLIST, (Appendable)w);
|
||||
}
|
||||
EXPLOSION_BLACKLIST.clear();
|
||||
EXPLOSION_BLACKLIST.addAll(DEFAULT_BLACKLIST);
|
||||
return;
|
||||
}
|
||||
try (BufferedReader r = Files.newBufferedReader(BLACKLIST_JSON);){
|
||||
List list = (List)gson.fromJson((Reader)r, new TypeToken<List<String>>(){}.getType());
|
||||
if (list != null) {
|
||||
EXPLOSION_BLACKLIST.clear();
|
||||
EXPLOSION_BLACKLIST.addAll(list);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOGGER.warn("Failed to load DestroyingBlacklist.json, falling back to defaults", (Throwable)e);
|
||||
EXPLOSION_BLACKLIST.clear();
|
||||
EXPLOSION_BLACKLIST.addAll(DEFAULT_BLACKLIST);
|
||||
}
|
||||
}
|
||||
|
||||
private static void loadSourceModesFromJson() {
|
||||
ExplosionOverhaul.ensureConfigDirectory();
|
||||
Gson gson = new GsonBuilder().setPrettyPrinting().create();
|
||||
try {
|
||||
if (!Files.exists(SOURCE_MODES_JSON, new LinkOption[0])) {
|
||||
ExplosionOverhaul.ensureConfigDirectory();
|
||||
SOURCE_MODES.clear();
|
||||
try (BufferedWriter w = Files.newBufferedWriter(SOURCE_MODES_JSON, new OpenOption[0]);){
|
||||
gson.toJson(SOURCE_MODES, (Appendable)w);
|
||||
}
|
||||
return;
|
||||
}
|
||||
try (BufferedReader r = Files.newBufferedReader(SOURCE_MODES_JSON);){
|
||||
Map map = (Map)gson.fromJson((Reader)r, new TypeToken<Map<String, ExplosionSourceMode>>(){}.getType());
|
||||
if (map != null) {
|
||||
SOURCE_MODES.clear();
|
||||
SOURCE_MODES.putAll(map);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOGGER.warn("Failed to load ExplosionSourceBlacklist.json", (Throwable)e);
|
||||
}
|
||||
}
|
||||
|
||||
public static ExplosionSourceMode getSourceMode(String id) {
|
||||
return SOURCE_MODES.getOrDefault(id, ExplosionSourceMode.DEFAULT);
|
||||
}
|
||||
|
||||
public static Map<String, ExplosionSourceMode> getSourceModes() {
|
||||
return new HashMap<String, ExplosionSourceMode>(SOURCE_MODES);
|
||||
}
|
||||
|
||||
public static void setSourceModes(Map<String, ExplosionSourceMode> modes) {
|
||||
SOURCE_MODES.clear();
|
||||
SOURCE_MODES.putAll(modes);
|
||||
Gson gson = new GsonBuilder().setPrettyPrinting().create();
|
||||
try (BufferedWriter w = Files.newBufferedWriter(SOURCE_MODES_JSON, new OpenOption[0]);){
|
||||
gson.toJson(SOURCE_MODES, (Appendable)w);
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOGGER.warn("Failed to save ExplosionSourceBlacklist.json", (Throwable)e);
|
||||
}
|
||||
}
|
||||
|
||||
public static List<String> getExplosionBlacklistList() {
|
||||
return new ArrayList<String>(EXPLOSION_BLACKLIST);
|
||||
}
|
||||
|
||||
public static List<String> getDefaultExplosionBlacklist() {
|
||||
return new ArrayList<String>(DEFAULT_BLACKLIST);
|
||||
}
|
||||
|
||||
public static void setExplosionBlacklistFromList(List<String> list) {
|
||||
EXPLOSION_BLACKLIST.clear();
|
||||
for (String s : list) {
|
||||
if (s == null || s.isBlank()) continue;
|
||||
EXPLOSION_BLACKLIST.add(s.trim());
|
||||
}
|
||||
Gson gson = new GsonBuilder().setPrettyPrinting().create();
|
||||
try (BufferedWriter w = Files.newBufferedWriter(BLACKLIST_JSON, new OpenOption[0]);){
|
||||
gson.toJson(ExplosionOverhaul.getExplosionBlacklistList(), (Appendable)w);
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOGGER.warn("Failed to save DestroyingBlacklist.json", (Throwable)e);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isBlockBlacklisted(Block block) {
|
||||
ResourceLocation blockId = ForgeRegistries.BLOCKS.getKey((Object)block);
|
||||
if (blockId != null) {
|
||||
String blockName = blockId.toString();
|
||||
return EXPLOSION_BLACKLIST.contains(blockName);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isBlockStateBlacklisted(BlockState state) {
|
||||
ResourceLocation blockId = ForgeRegistries.BLOCKS.getKey((Object)state.m_60734_());
|
||||
if (blockId != null) {
|
||||
String blockName = blockId.toString();
|
||||
return EXPLOSION_BLACKLIST.contains(blockName);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public ExplosionOverhaul() {
|
||||
IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus();
|
||||
GeckoLib.initialize();
|
||||
ModLoadingContext.get().registerConfig(ModConfig.Type.COMMON, (IConfigSpec)Config.COMMON_SPEC, "explosionoverhaul/explosionoverhaul-common.toml");
|
||||
ModLoadingContext.get().registerConfig(ModConfig.Type.CLIENT, (IConfigSpec)Config.CLIENT_SPEC, "explosionoverhaul/explosionoverhaul-client.toml");
|
||||
ModLoadingContext.get().registerExtensionPoint(ConfigScreenHandler.ConfigScreenFactory.class, () -> new ConfigScreenHandler.ConfigScreenFactory((client, parent) -> ModConfigScreen.create(parent)));
|
||||
ModSounds.register(modEventBus);
|
||||
ModParticles.register(modEventBus);
|
||||
ModBlocks.register(modEventBus);
|
||||
ModItems.register(modEventBus);
|
||||
ModBlockEntities.register(modEventBus);
|
||||
ModCreativeTabs.register(modEventBus);
|
||||
MinecraftForge.EVENT_BUS.register(ExplosionOverhaul.class);
|
||||
MinecraftForge.EVENT_BUS.register((Object)new ServerExplosionHandler());
|
||||
MinecraftForge.EVENT_BUS.register(BlockIndexManager.class);
|
||||
modEventBus.addListener(this::commonSetup);
|
||||
DistExecutor.unsafeRunWhenOn((Dist)Dist.CLIENT, () -> () -> {
|
||||
SoundPhysicsCompatibility.init();
|
||||
modEventBus.addListener(ClientSetup::init);
|
||||
modEventBus.addListener(ClientSetup::registerParticleFactories);
|
||||
modEventBus.addListener(ClientSetup::registerBlockEntityRenderers);
|
||||
modEventBus.addListener(ClientSetup::registerShaders);
|
||||
modEventBus.addListener(ClientSetup::registerReloadListeners);
|
||||
modEventBus.addListener(ClientSetup::onRegisterKeyMappings);
|
||||
MinecraftForge.EVENT_BUS.register(ClientSetup.class);
|
||||
MinecraftForge.EVENT_BUS.register((Object)new ClientSoundHandler());
|
||||
MinecraftForge.EVENT_BUS.register(ScanProgressHUD.class);
|
||||
MinecraftForge.EVENT_BUS.register(ScanPromptHUD.class);
|
||||
MinecraftForge.EVENT_BUS.register(ScanInfoHUD.class);
|
||||
MinecraftForge.EVENT_BUS.register(ScanLoadPromptHUD.class);
|
||||
MinecraftForge.EVENT_BUS.register(ScanLoadInfoHUD.class);
|
||||
MinecraftForge.EVENT_BUS.register((Object)new ScanKeyHandler());
|
||||
MinecraftForge.EVENT_BUS.register(FirstTimeSetupHandler.class);
|
||||
MinecraftForge.EVENT_BUS.register(IntroMusicTickHandler.class);
|
||||
MinecraftForge.EVENT_BUS.register(ConcussionAudioEffect.class);
|
||||
});
|
||||
}
|
||||
|
||||
private void commonSetup(FMLCommonSetupEvent event) {
|
||||
ExplosionOverhaul.migrateOldTomlIfPresent();
|
||||
ExplosionOverhaul.loadBlacklistFromJson();
|
||||
ExplosionOverhaul.loadSourceModesFromJson();
|
||||
event.enqueueWork(PacketHandler::register);
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onServerTick(TickEvent.ServerTickEvent event) {
|
||||
if (event.phase == TickEvent.Phase.END) {
|
||||
RedstoneLampEffects.onServerTick();
|
||||
if (event.getServer() != null) {
|
||||
for (ServerLevel level : event.getServer().m_129785_()) {
|
||||
DripstoneEffects.onServerTick(level);
|
||||
}
|
||||
}
|
||||
GlassBreakingEffects.onServerTick();
|
||||
AmbientExplosionManager.onServerTick(event.getServer().m_129783_());
|
||||
if (ServerLifecycleHooks.getCurrentServer() != null) {
|
||||
AsyncCraterManager.onServerTick(ServerLifecycleHooks.getCurrentServer());
|
||||
}
|
||||
delayedSounds.removeIf(delayedSound -> {
|
||||
--delayedSound.ticksRemaining;
|
||||
if (delayedSound.ticksRemaining <= 0L) {
|
||||
delayedSound.play();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
delayedParticles.removeIf(delayedParticle -> {
|
||||
--delayedParticle.ticksRemaining;
|
||||
if (delayedParticle.ticksRemaining <= 0L) {
|
||||
delayedParticle.spawn();
|
||||
if (delayedParticle.durationTicks > 1L) {
|
||||
--delayedParticle.durationTicks;
|
||||
delayedParticle.ticksRemaining = 1L;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onLevelUnload(LevelEvent.Unload event) {
|
||||
LevelAccessor levelAccessor = event.getLevel();
|
||||
if (levelAccessor instanceof ServerLevel) {
|
||||
ServerLevel level = (ServerLevel)levelAccessor;
|
||||
AsyncCraterManager.onLevelUnload(level);
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onServerStopped(ServerStoppedEvent event) {
|
||||
AsyncCraterManager.shutdown();
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onPlayerLogin(PlayerEvent.PlayerLoggedInEvent event) {
|
||||
if (event.getEntity() instanceof ServerPlayer) {
|
||||
AmbientExplosionManager.onPlayerLoggedIn((ServerPlayer)event.getEntity());
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onPlayerLogout(PlayerEvent.PlayerLoggedOutEvent event) {
|
||||
if (event.getEntity() instanceof ServerPlayer) {
|
||||
AmbientExplosionManager.onPlayerLoggedOut((ServerPlayer)event.getEntity());
|
||||
}
|
||||
}
|
||||
|
||||
public static void addDelayedSound(ServerPlayer player, SoundEvent sound, SoundSource source, float x, float y, float z, float volume, float pitch, long seed, long delayTicks) {
|
||||
if (player.f_8906_ == null) {
|
||||
return;
|
||||
}
|
||||
if (delayTicks <= 0L) {
|
||||
player.f_8906_.m_9829_((Packet)new ClientboundSoundPacket((Holder)ForgeRegistries.SOUND_EVENTS.getHolder((Object)sound).orElseThrow(), source, (double)x, (double)y, (double)z, volume, pitch, seed));
|
||||
} else {
|
||||
delayedSounds.add(new DelayedSound(player, sound, source, x, y, z, volume, pitch, seed, delayTicks));
|
||||
}
|
||||
}
|
||||
|
||||
public static void addDelayedParticle(ServerLevel level, BlockParticleOption particleOption, double x, double y, double z, int count, double dx, double dy, double dz, double speed, long delayTicks, long durationTicks) {
|
||||
if (delayTicks <= 0L && durationTicks <= 1L) {
|
||||
level.m_8767_((ParticleOptions)particleOption, x, y, z, count, dx, dy, dz, speed);
|
||||
} else {
|
||||
delayedParticles.add(new DelayedParticle(level, particleOption, x, y, z, count, dx, dy, dz, speed, delayTicks, Math.max(1L, durationTicks)));
|
||||
}
|
||||
}
|
||||
|
||||
public static enum ExplosionSourceMode {
|
||||
DEFAULT,
|
||||
VANILLA,
|
||||
NO_DESTRUCTION,
|
||||
NO_DESTRUCTION_GLASSWORKS;
|
||||
|
||||
}
|
||||
|
||||
public static class DelayedSound {
|
||||
public ServerPlayer player;
|
||||
public SoundEvent sound;
|
||||
public SoundSource source;
|
||||
public float x;
|
||||
public float y;
|
||||
public float z;
|
||||
public float volume;
|
||||
public float pitch;
|
||||
public long seed;
|
||||
public long ticksRemaining;
|
||||
|
||||
public DelayedSound(ServerPlayer player, SoundEvent sound, SoundSource source, float x, float y, float z, float volume, float pitch, long seed, long ticksRemaining) {
|
||||
this.player = player;
|
||||
this.sound = sound;
|
||||
this.source = source;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.volume = volume;
|
||||
this.pitch = pitch;
|
||||
this.seed = seed;
|
||||
this.ticksRemaining = ticksRemaining;
|
||||
}
|
||||
|
||||
public void play() {
|
||||
if (this.player.f_8906_ == null) {
|
||||
return;
|
||||
}
|
||||
this.player.f_8906_.m_9829_((Packet)new ClientboundSoundPacket((Holder)ForgeRegistries.SOUND_EVENTS.getHolder((Object)this.sound).orElseThrow(), this.source, (double)this.x, (double)this.y, (double)this.z, this.volume, this.pitch, this.seed));
|
||||
}
|
||||
}
|
||||
|
||||
public static class DelayedParticle {
|
||||
public ServerLevel level;
|
||||
public BlockParticleOption particleOption;
|
||||
public double x;
|
||||
public double y;
|
||||
public double z;
|
||||
public int count;
|
||||
public double dx;
|
||||
public double dy;
|
||||
public double dz;
|
||||
public double speed;
|
||||
public long ticksRemaining;
|
||||
public long durationTicks;
|
||||
|
||||
public DelayedParticle(ServerLevel level, BlockParticleOption particleOption, double x, double y, double z, int count, double dx, double dy, double dz, double speed, long ticksRemaining, long durationTicks) {
|
||||
this.level = level;
|
||||
this.particleOption = particleOption;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.count = count;
|
||||
this.dx = dx;
|
||||
this.dy = dy;
|
||||
this.dz = dz;
|
||||
this.speed = speed;
|
||||
this.ticksRemaining = ticksRemaining;
|
||||
this.durationTicks = durationTicks;
|
||||
}
|
||||
|
||||
public void spawn() {
|
||||
int particlesPerSpawn = Math.max(1, this.count / (int)Math.max(1L, this.durationTicks));
|
||||
this.level.m_8767_((ParticleOptions)this.particleOption, this.x, this.y, this.z, particlesPerSpawn, this.dx, this.dy, this.dz, this.speed);
|
||||
}
|
||||
}
|
||||
|
||||
public static class ClientSetup {
|
||||
private static boolean hasPreWarmed = false;
|
||||
|
||||
public static void init(FMLClientSetupEvent event) {
|
||||
ExplosionTextureManager.getInstance().reload();
|
||||
}
|
||||
|
||||
public static void registerReloadListeners(RegisterClientReloadListenersEvent event) {
|
||||
event.registerReloadListener((PreparableReloadListener)new TexturePreloader());
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void registerShaders(RegisterShadersEvent event) {
|
||||
try {
|
||||
event.registerShader(new ShaderInstance(event.getResourceProvider(), new ResourceLocation(ExplosionOverhaul.MODID, "blur"), DefaultVertexFormat.f_85817_), Blur::setShader);
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOGGER.warn("Failed to load core shaders", (Throwable)e);
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void registerParticleFactories(RegisterParticleProvidersEvent event) {
|
||||
event.registerSpriteSet((ParticleType)ModParticles.CUSTOM_GLOW.get(), CustomGlowParticleProvider::new);
|
||||
event.registerSpriteSet((ParticleType)ModParticles.PLASMA.get(), PlasmaParticle.Provider::new);
|
||||
event.registerSpriteSet((ParticleType)ModParticles.CUSTOM_SMOKE.get(), SmokeParticle.Provider::new);
|
||||
event.registerSpriteSet((ParticleType)ModParticles.LINE_SPARK.get(), LineSparkParticleProvider::new);
|
||||
LOGGER.info("Registered custom particle providers.");
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onRegisterKeyMappings(RegisterKeyMappingsEvent event) {
|
||||
ModKeyMappings.register(event);
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void registerBlockEntityRenderers(EntityRenderersEvent.RegisterRenderers event) {
|
||||
event.registerBlockEntityRenderer((BlockEntityType)ModBlockEntities.VINLANX_THE_LIGHT.get(), VinlanxTheLightRenderer::new);
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onClientTick(TickEvent.ClientTickEvent event) {
|
||||
if (event.phase == TickEvent.Phase.END) {
|
||||
ClientEffects.onClientTick();
|
||||
if (!hasPreWarmed && Minecraft.m_91087_().f_91073_ != null && Minecraft.m_91087_().f_91074_ != null) {
|
||||
LOGGER.info("Pre-warming explosion particle render pipeline...");
|
||||
ClientLevel level = Minecraft.m_91087_().f_91073_;
|
||||
double x = Minecraft.m_91087_().f_91074_.m_20185_();
|
||||
double y = -200.0;
|
||||
double z = Minecraft.m_91087_().f_91074_.m_20189_();
|
||||
level.m_7106_((ParticleOptions)new PlasmaParticleOptions(1.0f), x, y, z, 0.0, 0.0, 0.0);
|
||||
LOGGER.info("Pre-warming 'glow' animation...");
|
||||
level.m_7106_((ParticleOptions)new CustomGlowParticleOptions(0, 1.0f, 0.01f, 0, (float)y, 4.0f, 0.0f), x, y, z, 0.0, 0.0, 0.0);
|
||||
LOGGER.info("Pre-warming 'glow_2' animation...");
|
||||
level.m_7106_((ParticleOptions)new CustomGlowParticleOptions(0, 1.0f, 0.01f, 1, (float)y, 4.0f, 0.0f), x, y, z, 0.0, 0.0, 0.0);
|
||||
LOGGER.info("Pre-warming 'sglow' animation...");
|
||||
level.m_7106_((ParticleOptions)new CustomGlowParticleOptions(0, 1.0f, 0.01f, 2, (float)y, 4.0f, 0.0f), x, y, z, 0.0, 0.0, 0.0);
|
||||
hasPreWarmed = true;
|
||||
LOGGER.info("Explosion particle pipeline pre-warmed successfully.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onPlayerLogout(ClientPlayerNetworkEvent.LoggingOut event) {
|
||||
LOGGER.info("Player logged out, resetting particle pre-warmer and scan HUDs.");
|
||||
hasPreWarmed = false;
|
||||
ExplosionWindController.reset();
|
||||
ScanProgressHUD.reset();
|
||||
ScanPromptHUD.setVisible(false);
|
||||
ScanLoadPromptHUD.setVisible(false);
|
||||
ScanInfoHUD.setVisible(false);
|
||||
ScanLoadInfoHUD.setVisible(false);
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onRenderGuiOverlay(RenderGuiOverlayEvent.Post event) {
|
||||
if (event.getOverlay().id().m_135815_().equals("all")) {
|
||||
Blur.render(Blur.RenderStage.HUD);
|
||||
}
|
||||
if (event.getOverlay().id().m_135815_().equals("crosshair")) {
|
||||
ClientEffects.renderFlash(event);
|
||||
ConcussionAudioEffect.renderHeartbeatHUD(event.getGuiGraphics());
|
||||
}
|
||||
}
|
||||
|
||||
public static class TexturePreloader
|
||||
implements PreparableReloadListener {
|
||||
public CompletableFuture<Void> m_5540_(PreparableReloadListener.PreparationBarrier pPreparationBarrier, ResourceManager pResourceManager, ProfilerFiller pPreparationsProfiler, ProfilerFiller pReloadProfiler, Executor pBackgroundExecutor, Executor pGameExecutor) {
|
||||
CompletableFuture<List> prepareFuture = CompletableFuture.supplyAsync(() -> {
|
||||
LOGGER.info("Scanning for all mod textures to preload...");
|
||||
return pResourceManager.m_214159_("textures", path -> path.m_135827_().equals(ExplosionOverhaul.MODID) && path.m_135815_().endsWith(".png")).keySet().stream().toList();
|
||||
}, pBackgroundExecutor);
|
||||
return prepareFuture.thenCompose(locationsToLoad -> pPreparationBarrier.m_6769_(locationsToLoad).thenRunAsync(() -> {
|
||||
if (locationsToLoad.isEmpty()) {
|
||||
LOGGER.warn("Did not find any textures to preload for mod '{}'.", (Object)ExplosionOverhaul.MODID);
|
||||
return;
|
||||
}
|
||||
LOGGER.info("Preloading {} textures from '{}' to GPU...", (Object)locationsToLoad.size(), (Object)ExplosionOverhaul.MODID);
|
||||
TextureManager textureManager = Minecraft.m_91087_().m_91097_();
|
||||
for (ResourceLocation location : locationsToLoad) {
|
||||
textureManager.m_118506_(location);
|
||||
}
|
||||
ExplosionTextureManager.getInstance().reload();
|
||||
LOGGER.info("Finished preloading all textures for the mod.");
|
||||
}, pGameExecutor));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class CaveEffects {
|
||||
private static final int PLAYER_EFFECT_RADIUS = 10;
|
||||
|
||||
public static void spawnFallingBlocksAndDust(ServerLevel level, Vec3 explosionPos, ServerPlayer player, float power, long initialDelayTicks) {
|
||||
RandomSource random = level.m_213780_();
|
||||
long maxEffectOverallDurationTicks = (2 + random.m_188503_(5)) * 20;
|
||||
int totalEffectSpawns = 15 + (int)(power / 5.0f * 3.0f);
|
||||
totalEffectSpawns = Math.min(totalEffectSpawns, 60);
|
||||
for (int i = 0; i < totalEffectSpawns; ++i) {
|
||||
long individualDelay = initialDelayTicks + (long)random.m_188503_((int)maxEffectOverallDurationTicks / 2);
|
||||
long randomDurationTicks = 10 + random.m_188503_(40);
|
||||
CaveEffects.spawnEffectAtPlayer(level, player, individualDelay, random, power, randomDurationTicks);
|
||||
}
|
||||
}
|
||||
|
||||
private static void spawnEffectAtPlayer(ServerLevel level, ServerPlayer player, long delayTicks, RandomSource random, float power, long durationTicks) {
|
||||
int xOffset = random.m_188503_(21) - 10;
|
||||
int zOffset = random.m_188503_(21) - 10;
|
||||
int ySearchStart = (int)player.m_20186_() + 3 + random.m_188503_(4);
|
||||
BlockPos playerBlockPos = player.m_20183_();
|
||||
BlockPos checkPosBase = new BlockPos(playerBlockPos.m_123341_() + xOffset, ySearchStart, playerBlockPos.m_123343_() + zOffset);
|
||||
BlockPos effectPos = null;
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
BlockState aboveState;
|
||||
BlockState currentState;
|
||||
BlockPos currentCheck = checkPosBase.m_6625_(i);
|
||||
if (!level.m_46749_(currentCheck) || (double)currentCheck.m_123342_() <= player.m_20186_() - 1.0 || !(currentState = level.m_8055_(currentCheck)).m_280296_() || currentState.m_60795_() || !(aboveState = level.m_8055_(currentCheck.m_7494_())).m_60795_() && !level.m_8055_(currentCheck.m_7495_()).m_60795_()) continue;
|
||||
effectPos = currentCheck;
|
||||
break;
|
||||
}
|
||||
if (effectPos != null && effectPos.m_123342_() > level.m_141937_()) {
|
||||
boolean isSpecialBlock;
|
||||
BlockState blockState = level.m_8055_(effectPos);
|
||||
if (blockState.m_60795_()) {
|
||||
return;
|
||||
}
|
||||
ResourceLocation registryName = ForgeRegistries.BLOCKS.getKey((Object)blockState.m_60734_());
|
||||
String name = registryName != null ? registryName.m_135815_() : "";
|
||||
boolean bl = isSpecialBlock = name.contains("bedrock") || name.contains("end_portal") || name.contains("end_portal_frame") || name.contains("command_block") || name.contains("barrier");
|
||||
if (isSpecialBlock) {
|
||||
return;
|
||||
}
|
||||
int particleCount = 8 + (int)((double)(power / 10.0f) * 1.5);
|
||||
particleCount = Math.min(particleCount, 25);
|
||||
ExplosionOverhaul.addDelayedParticle(level, new BlockParticleOption(ParticleTypes.f_123814_, blockState), (double)effectPos.m_123341_() + 0.5, (double)effectPos.m_123342_() + 0.2, (double)effectPos.m_123343_() + 0.5, particleCount, 0.3, 0.3, 0.3, 0.02, delayTicks, durationTicks);
|
||||
if (random.m_188500_() < 0.3 + (double)power * 0.02) {
|
||||
ExplosionOverhaul.addDelayedSound(player, (SoundEvent)ModSounds.DUST_SOUND.get(), SoundSource.BLOCKS, (float)effectPos.m_123341_() + 0.5f, (float)effectPos.m_123342_() + 0.5f, (float)effectPos.m_123343_() + 0.5f, 0.6f + random.m_188501_() * 0.4f, 0.85f + random.m_188501_() * 0.3f, player.m_217043_().m_188505_(), delayTicks + (long)random.m_188503_(10));
|
||||
}
|
||||
if (random.m_188500_() < 0.03 + (double)power * 0.005 && power > 10.0f) {
|
||||
ExplosionOverhaul.addDelayedSound(player, (SoundEvent)ModSounds.FALLING_STONES_SOUND.get(), SoundSource.BLOCKS, (float)effectPos.m_123341_() + 0.5f, (float)effectPos.m_123342_() + 0.5f, (float)effectPos.m_123343_() + 0.5f, 0.8f + random.m_188501_() * 0.2f, 0.9f + random.m_188501_() * 0.2f, player.m_217043_().m_188505_(), delayTicks + (long)random.m_188503_(20));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul;
|
||||
|
||||
import com.vinlanx.explosionoverhaul.client.ClientEffects;
|
||||
import java.util.function.Supplier;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.neoforged.neoforge.network.NetworkEvent;
|
||||
|
||||
public class ExplosionVisualsPacket {
|
||||
private final Vec3 position;
|
||||
private final float power;
|
||||
|
||||
public ExplosionVisualsPacket(Vec3 position, float power) {
|
||||
this.position = position;
|
||||
this.power = power;
|
||||
}
|
||||
|
||||
public static void encode(ExplosionVisualsPacket msg, FriendlyByteBuf buf) {
|
||||
buf.writeDouble(msg.position.f_82479_);
|
||||
buf.writeDouble(msg.position.f_82480_);
|
||||
buf.writeDouble(msg.position.f_82481_);
|
||||
buf.writeFloat(msg.power);
|
||||
}
|
||||
|
||||
public static ExplosionVisualsPacket decode(FriendlyByteBuf buf) {
|
||||
return new ExplosionVisualsPacket(new Vec3(buf.readDouble(), buf.readDouble(), buf.readDouble()), buf.readFloat());
|
||||
}
|
||||
|
||||
public static void handle(ExplosionVisualsPacket msg, Supplier<NetworkEvent.Context> ctx) {
|
||||
ctx.get().enqueueWork(() -> ClientEffects.triggerRealisticExplosion(msg.position, msg.power));
|
||||
ctx.get().setPacketHandled(true);
|
||||
}
|
||||
|
||||
public Vec3 getPosition() {
|
||||
return this.position;
|
||||
}
|
||||
|
||||
public float getPower() {
|
||||
return this.power;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul;
|
||||
|
||||
import com.vinlanx.explosionoverhaul.client.ClientEffects;
|
||||
import java.util.function.Supplier;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.neoforged.api.distmarker.Dist;
|
||||
import net.neoforged.fml.DistExecutor;
|
||||
import net.neoforged.neoforge.network.NetworkEvent;
|
||||
|
||||
public class FlashEffectPacket {
|
||||
private final Vec3 explosionPos;
|
||||
private final float power;
|
||||
|
||||
public FlashEffectPacket(Vec3 explosionPos, float power) {
|
||||
this.explosionPos = explosionPos;
|
||||
this.power = power;
|
||||
}
|
||||
|
||||
public static void encode(FlashEffectPacket msg, FriendlyByteBuf buf) {
|
||||
buf.writeDouble(msg.explosionPos.f_82479_);
|
||||
buf.writeDouble(msg.explosionPos.f_82480_);
|
||||
buf.writeDouble(msg.explosionPos.f_82481_);
|
||||
buf.writeFloat(msg.power);
|
||||
}
|
||||
|
||||
public static FlashEffectPacket decode(FriendlyByteBuf buf) {
|
||||
return new FlashEffectPacket(new Vec3(buf.readDouble(), buf.readDouble(), buf.readDouble()), buf.readFloat());
|
||||
}
|
||||
|
||||
public static void handle(FlashEffectPacket msg, Supplier<NetworkEvent.Context> ctx) {
|
||||
ctx.get().enqueueWork(() -> DistExecutor.unsafeRunWhenOn((Dist)Dist.CLIENT, () -> () -> ClientEffects.addFlashEffect(msg.explosionPos, msg.power)));
|
||||
ctx.get().setPacketHandled(true);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,230 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul;
|
||||
|
||||
import com.vinlanx.explosionoverhaul.BlockIndexManager;
|
||||
import com.vinlanx.explosionoverhaul.Config;
|
||||
import com.vinlanx.explosionoverhaul.ExplosionOverhaul;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.Position;
|
||||
import net.minecraft.core.Vec3i;
|
||||
import net.minecraft.core.particles.BlockParticleOption;
|
||||
import net.minecraft.core.particles.ParticleOptions;
|
||||
import net.minecraft.core.particles.ParticleTypes;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.sounds.SoundEvents;
|
||||
import net.minecraft.sounds.SoundSource;
|
||||
import net.minecraft.tags.BlockTags;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.level.BlockGetter;
|
||||
import net.minecraft.world.level.ClipContext;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.HitResult;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
public class GlassBreakingEffects {
|
||||
private static final Map<UUID, List<DelayedGlassEffect>> perExplosionEffects = new ConcurrentHashMap<UUID, List<DelayedGlassEffect>>();
|
||||
private static final int MAX_GROUPS_PER_EXPLOSION = 250;
|
||||
private static int tickCounter = 0;
|
||||
|
||||
public static void trigger(ServerLevel level, Vec3 explosionPos, float power) {
|
||||
if (!((Boolean)Config.COMMON.enableGlassBreaking.get()).booleanValue()) {
|
||||
return;
|
||||
}
|
||||
RandomSource random = level.m_213780_();
|
||||
double radius = GlassBreakingEffects.calculateRadius(power);
|
||||
BlockPos center = BlockPos.m_274446_((Position)explosionPos);
|
||||
List<BlockPos> glassBlocks = BlockIndexManager.getNearby(level, center, (int)Math.ceil(radius), BlockIndexManager.BlockType.GLASS);
|
||||
if (glassBlocks.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
HashSet<BlockPos> foundGlassBlocks = new HashSet<BlockPos>();
|
||||
float initialRayEnergy = power * 2.5f;
|
||||
block0: for (BlockPos glassPos : glassBlocks) {
|
||||
Vec3 glassCenter = Vec3.m_82512_((Vec3i)glassPos);
|
||||
Vec3 rayDirection = glassCenter.m_82546_(explosionPos).m_82541_();
|
||||
double distanceToGlass = explosionPos.m_82554_(glassCenter);
|
||||
if (distanceToGlass > radius) continue;
|
||||
float currentEnergy = initialRayEnergy * (0.8f + random.m_188501_() * 0.4f);
|
||||
BlockPos lastPos = null;
|
||||
for (double step = 0.5; step < distanceToGlass + 1.0; step += 0.4) {
|
||||
float resistance;
|
||||
BlockPos currentPos = BlockPos.m_274446_((Position)explosionPos.m_82549_(rayDirection.m_82490_(step)));
|
||||
if (currentPos.equals(lastPos)) continue;
|
||||
lastPos = currentPos;
|
||||
if (!level.m_46749_(currentPos) || currentPos.m_123342_() < level.m_141937_() || currentPos.m_123342_() >= level.m_151558_()) continue block0;
|
||||
BlockState state = level.m_8055_(currentPos);
|
||||
if (state.m_60795_()) continue;
|
||||
if (GlassBreakingEffects.isGlass(state)) {
|
||||
foundGlassBlocks.add(currentPos);
|
||||
continue;
|
||||
}
|
||||
if (BlockIndexManager.isReinforcedGlass(state) || ExplosionOverhaul.isBlockStateBlacklisted(state) || (currentEnergy -= (resistance = state.getExplosionResistance((BlockGetter)level, currentPos, null)) + 0.3f) <= 0.0f) continue block0;
|
||||
}
|
||||
}
|
||||
if (foundGlassBlocks.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
ArrayList<GlassGroup> groups = new ArrayList<GlassGroup>();
|
||||
HashSet<BlockPos> processed = new HashSet<BlockPos>();
|
||||
for (BlockPos glassPos : foundGlassBlocks) {
|
||||
List<BlockPos> groupPositions;
|
||||
if (processed.contains(glassPos) || (groupPositions = GlassBreakingEffects.findConnectedGlass(level, glassPos, processed)).isEmpty()) continue;
|
||||
groups.add(new GlassGroup(groupPositions, glassPos, glassPos.m_123331_((Vec3i)center)));
|
||||
}
|
||||
if (groups.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
groups.sort(Comparator.comparingDouble(g -> g.distanceSq));
|
||||
List<DelayedGlassEffect> effects = Collections.synchronizedList(new ArrayList());
|
||||
UUID explosionId = UUID.randomUUID();
|
||||
int groupsToProcess = Math.min(groups.size(), 250);
|
||||
for (int i = 0; i < groupsToProcess; ++i) {
|
||||
GlassGroup group = (GlassGroup)groups.get(i);
|
||||
for (BlockPos pos : group.positions()) {
|
||||
if (!GlassBreakingEffects.shouldBreak(level, explosionPos, pos, power, random, radius)) continue;
|
||||
double distance = Math.sqrt(pos.m_123331_((Vec3i)BlockPos.m_274446_((Position)explosionPos)));
|
||||
long delayInTicks = (long)(distance / 3.0);
|
||||
int processingInterval = Math.max(1, (Integer)Config.COMMON.glassBreakingIntervalTicks.get());
|
||||
long delayInProcessingCycles = Math.max(1L, delayInTicks / (long)processingInterval);
|
||||
effects.add(new DelayedGlassEffect(level, pos, delayInProcessingCycles += (long)random.m_188503_(2)));
|
||||
}
|
||||
}
|
||||
if (!effects.isEmpty()) {
|
||||
perExplosionEffects.put(explosionId, effects);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean shouldBreak(ServerLevel level, Vec3 explosionPos, BlockPos glassPos, float power, RandomSource random, double maxRadius) {
|
||||
ClipContext context;
|
||||
double distance = Math.sqrt(glassPos.m_123331_((Vec3i)BlockPos.m_274446_((Position)explosionPos)));
|
||||
float distanceFraction = (float)(distance / maxRadius);
|
||||
if (distanceFraction > 1.0f) {
|
||||
return false;
|
||||
}
|
||||
float baseChance = distanceFraction <= 0.25f ? Mth.m_14179_((float)(distanceFraction / 0.25f), (float)1.0f, (float)0.95f) : (distanceFraction <= 0.5f ? Mth.m_14179_((float)((distanceFraction - 0.25f) / 0.25f), (float)0.95f, (float)0.68f) : (distanceFraction <= 0.85f ? Mth.m_14179_((float)((distanceFraction - 0.5f) / 0.35f), (float)0.68f, (float)0.2f) : Mth.m_14179_((float)((distanceFraction - 0.85f) / 0.15f), (float)0.2f, (float)0.0f)));
|
||||
baseChance *= Mth.m_14036_((float)(power / 25.0f), (float)0.8f, (float)1.5f);
|
||||
BlockState state = level.m_8055_(glassPos);
|
||||
if (state.m_60734_().toString().contains("pane")) {
|
||||
baseChance += 0.2f;
|
||||
}
|
||||
if (level.m_45547_(context = new ClipContext(explosionPos, Vec3.m_82512_((Vec3i)glassPos), ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, null)).m_6662_() != HitResult.Type.MISS) {
|
||||
baseChance *= 0.5f;
|
||||
}
|
||||
return random.m_188501_() < Mth.m_14036_((float)baseChance, (float)0.0f, (float)1.0f);
|
||||
}
|
||||
|
||||
private static double calculateRadius(float power) {
|
||||
if (power <= 5.0f) {
|
||||
return Mth.m_14179_((float)Mth.m_184655_((float)power, (float)1.0f, (float)4.0f), (float)20.0f, (float)48.0f);
|
||||
}
|
||||
float dustRadius = power * GlassBreakingEffects.calculateRadiusMultiplier(power);
|
||||
return dustRadius * 1.75f;
|
||||
}
|
||||
|
||||
private static float calculateRadiusMultiplier(float power) {
|
||||
if (power <= 5.0f) {
|
||||
return 2.0f;
|
||||
}
|
||||
if (power <= 40.0f) {
|
||||
return Mth.m_14179_((float)((power - 5.0f) / 35.0f), (float)2.0f, (float)4.0f);
|
||||
}
|
||||
if (power <= 80.0f) {
|
||||
return Mth.m_14179_((float)((power - 40.0f) / 40.0f), (float)4.0f, (float)5.0f);
|
||||
}
|
||||
if (power <= 100.0f) {
|
||||
return Mth.m_14179_((float)((power - 80.0f) / 20.0f), (float)5.0f, (float)7.0f);
|
||||
}
|
||||
return 7.0f;
|
||||
}
|
||||
|
||||
private static List<BlockPos> findConnectedGlass(ServerLevel level, BlockPos start, Set<BlockPos> processed) {
|
||||
ArrayList<BlockPos> group = new ArrayList<BlockPos>();
|
||||
LinkedList<BlockPos> queue = new LinkedList<BlockPos>();
|
||||
queue.add(start);
|
||||
processed.add(start);
|
||||
while (!queue.isEmpty()) {
|
||||
BlockPos current = (BlockPos)queue.poll();
|
||||
group.add(current);
|
||||
if (group.size() > 200) break;
|
||||
for (Direction dir : Direction.values()) {
|
||||
BlockPos neighbor = current.m_5484_(dir, 1);
|
||||
if (processed.contains(neighbor) || !GlassBreakingEffects.isGlass(level.m_8055_(neighbor))) continue;
|
||||
processed.add(neighbor);
|
||||
queue.add(neighbor);
|
||||
}
|
||||
}
|
||||
return group;
|
||||
}
|
||||
|
||||
private static boolean isGlass(BlockState state) {
|
||||
if (BlockIndexManager.isReinforcedGlass(state)) {
|
||||
return false;
|
||||
}
|
||||
return state.m_204336_(BlockTags.f_13049_) || state.m_60734_().toString().contains("glass");
|
||||
}
|
||||
|
||||
public static void onServerTick() {
|
||||
int processingInterval = (Integer)Config.COMMON.glassBreakingIntervalTicks.get();
|
||||
if (++tickCounter < processingInterval) {
|
||||
return;
|
||||
}
|
||||
tickCounter = 0;
|
||||
if (perExplosionEffects.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
int budgetPerExplosion = (Integer)Config.COMMON.glassBlocksPerCycle.get();
|
||||
for (List<DelayedGlassEffect> effects : perExplosionEffects.values()) {
|
||||
int explosionBudget = budgetPerExplosion;
|
||||
Iterator<DelayedGlassEffect> iterator = effects.iterator();
|
||||
while (iterator.hasNext() && explosionBudget > 0) {
|
||||
DelayedGlassEffect effect = iterator.next();
|
||||
if (!effect.tick()) continue;
|
||||
iterator.remove();
|
||||
--explosionBudget;
|
||||
}
|
||||
}
|
||||
perExplosionEffects.values().removeIf(List::isEmpty);
|
||||
}
|
||||
|
||||
private record GlassGroup(List<BlockPos> positions, BlockPos representativePos, double distanceSq) {
|
||||
}
|
||||
|
||||
private static class DelayedGlassEffect {
|
||||
private final ServerLevel level;
|
||||
private final BlockPos glassPos;
|
||||
private final BlockState glassState;
|
||||
private long delayCycles;
|
||||
|
||||
public DelayedGlassEffect(ServerLevel level, BlockPos glassPos, long delayCycles) {
|
||||
this.level = level;
|
||||
this.glassPos = glassPos;
|
||||
this.glassState = level.m_8055_(glassPos);
|
||||
this.delayCycles = delayCycles;
|
||||
}
|
||||
|
||||
public boolean tick() {
|
||||
if (--this.delayCycles <= 0L) {
|
||||
this.level.m_46961_(this.glassPos, false);
|
||||
this.level.m_8767_((ParticleOptions)new BlockParticleOption(ParticleTypes.f_123794_, this.glassState), (double)this.glassPos.m_123341_() + 0.5, (double)this.glassPos.m_123342_() + 0.5, (double)this.glassPos.m_123343_() + 0.5, 20, 0.3, 0.3, 0.3, 0.1);
|
||||
this.level.m_5594_(null, this.glassPos, SoundEvents.f_11983_, SoundSource.BLOCKS, 0.7f, 1.0f);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul;
|
||||
|
||||
import com.vinlanx.explosionoverhaul.client.LowPassConcussionEffect;
|
||||
import java.util.function.Supplier;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.neoforged.api.distmarker.Dist;
|
||||
import net.neoforged.api.distmarker.OnlyIn;
|
||||
import net.neoforged.neoforge.network.NetworkEvent;
|
||||
|
||||
public class LowPassTestPacket {
|
||||
private final int durationSeconds;
|
||||
|
||||
public LowPassTestPacket(int durationSeconds) {
|
||||
this.durationSeconds = durationSeconds;
|
||||
}
|
||||
|
||||
public static void encode(LowPassTestPacket msg, FriendlyByteBuf buf) {
|
||||
buf.writeInt(msg.durationSeconds);
|
||||
}
|
||||
|
||||
public static LowPassTestPacket decode(FriendlyByteBuf buf) {
|
||||
return new LowPassTestPacket(buf.readInt());
|
||||
}
|
||||
|
||||
public static void handle(LowPassTestPacket msg, Supplier<NetworkEvent.Context> ctxSupplier) {
|
||||
NetworkEvent.Context ctx = ctxSupplier.get();
|
||||
ctx.enqueueWork(() -> LowPassTestPacket.handleClient(msg));
|
||||
ctx.setPacketHandled(true);
|
||||
}
|
||||
|
||||
@OnlyIn(value=Dist.CLIENT)
|
||||
private static void handleClient(LowPassTestPacket msg) {
|
||||
LowPassConcussionEffect.start(msg.durationSeconds, 0.5f);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul;
|
||||
|
||||
import com.vinlanx.explosionoverhaul.ModBlocks;
|
||||
import com.vinlanx.explosionoverhaul.VinlanxTheLightBlockEntity;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import net.neoforged.bus.api.IEventBus;
|
||||
import net.neoforged.neoforge.registries.DeferredRegister;
|
||||
import net.neoforged.neoforge.registries.ForgeRegistries;
|
||||
import net.neoforged.neoforge.registries.IForgeRegistry;
|
||||
import net.neoforged.neoforge.registries.RegistryObject;
|
||||
|
||||
public class ModBlockEntities {
|
||||
public static final DeferredRegister<BlockEntityType<?>> BLOCK_ENTITIES = DeferredRegister.create((IForgeRegistry)ForgeRegistries.BLOCK_ENTITY_TYPES, (String)"explosionoverhaul");
|
||||
public static final RegistryObject<BlockEntityType<VinlanxTheLightBlockEntity>> VINLANX_THE_LIGHT = BLOCK_ENTITIES.register("vinlanx_the_light", () -> BlockEntityType.Builder.m_155273_(VinlanxTheLightBlockEntity::new, (Block[])new Block[]{(Block)ModBlocks.VINLANX_THE_LIGHT.get()}).m_58966_(null));
|
||||
|
||||
public static void register(IEventBus eventBus) {
|
||||
BLOCK_ENTITIES.register(eventBus);
|
||||
}
|
||||
}
|
||||
21
src/main/java/com/vinlanx/explosionoverhaul/ModBlocks.java
Normal file
21
src/main/java/com/vinlanx/explosionoverhaul/ModBlocks.java
Normal file
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul;
|
||||
|
||||
import com.vinlanx.explosionoverhaul.VinlanxTheLightBlock;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.neoforged.bus.api.IEventBus;
|
||||
import net.neoforged.neoforge.registries.DeferredRegister;
|
||||
import net.neoforged.neoforge.registries.ForgeRegistries;
|
||||
import net.neoforged.neoforge.registries.IForgeRegistry;
|
||||
import net.neoforged.neoforge.registries.RegistryObject;
|
||||
|
||||
public class ModBlocks {
|
||||
public static final DeferredRegister<Block> BLOCKS = DeferredRegister.create((IForgeRegistry)ForgeRegistries.BLOCKS, (String)"explosionoverhaul");
|
||||
public static final RegistryObject<Block> VINLANX_THE_LIGHT = BLOCKS.register("vinlanx_the_light", () -> new VinlanxTheLightBlock(VinlanxTheLightBlock.defaultProperties()));
|
||||
|
||||
public static void register(IEventBus eventBus) {
|
||||
BLOCKS.register(eventBus);
|
||||
}
|
||||
}
|
||||
130
src/main/java/com/vinlanx/explosionoverhaul/ModCommands.java
Normal file
130
src/main/java/com/vinlanx/explosionoverhaul/ModCommands.java
Normal file
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul;
|
||||
|
||||
import com.mojang.brigadier.CommandDispatcher;
|
||||
import com.mojang.brigadier.arguments.ArgumentType;
|
||||
import com.mojang.brigadier.arguments.FloatArgumentType;
|
||||
import com.mojang.brigadier.arguments.IntegerArgumentType;
|
||||
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
|
||||
import com.vinlanx.explosionoverhaul.BlockIndexManager;
|
||||
import com.vinlanx.explosionoverhaul.BlurTestPacket;
|
||||
import com.vinlanx.explosionoverhaul.CameraShakeConcussionPacket;
|
||||
import com.vinlanx.explosionoverhaul.ExplosionOverhaul;
|
||||
import com.vinlanx.explosionoverhaul.LowPassTestPacket;
|
||||
import com.vinlanx.explosionoverhaul.ModParticles;
|
||||
import com.vinlanx.explosionoverhaul.OpenALTogglePacket;
|
||||
import com.vinlanx.explosionoverhaul.PacketHandler;
|
||||
import com.vinlanx.explosionoverhaul.SpawnCustomGlowPacket;
|
||||
import java.util.Arrays;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.commands.Commands;
|
||||
import net.minecraft.commands.SharedSuggestionProvider;
|
||||
import net.minecraft.commands.arguments.coordinates.Vec3Argument;
|
||||
import net.minecraft.core.particles.ParticleOptions;
|
||||
import net.minecraft.core.particles.SimpleParticleType;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.neoforged.neoforge.event.RegisterCommandsEvent;
|
||||
import net.neoforged.bus.api.SubscribeEvent;
|
||||
import net.neoforged.fml.common.Mod;
|
||||
import net.neoforged.neoforge.network.PacketDistributor;
|
||||
|
||||
@Mod.EventBusSubscriber(modid="explosionoverhaul")
|
||||
public class ModCommands {
|
||||
@SubscribeEvent
|
||||
public static void onCommandsRegister(RegisterCommandsEvent event) {
|
||||
CommandDispatcher dispatcher = event.getDispatcher();
|
||||
dispatcher.register((LiteralArgumentBuilder)((LiteralArgumentBuilder)Commands.m_82127_((String)"modparticle").requires(source -> source.m_6761_(2))).then(Commands.m_82129_((String)"pos", (ArgumentType)Vec3Argument.m_120841_()).then(Commands.m_82129_((String)"zone", (ArgumentType)IntegerArgumentType.integer((int)0, (int)1)).then(Commands.m_82129_((String)"power", (ArgumentType)FloatArgumentType.floatArg((float)1.0f)).then(Commands.m_82129_((String)"scale", (ArgumentType)FloatArgumentType.floatArg((float)0.1f)).then(Commands.m_82129_((String)"count", (ArgumentType)IntegerArgumentType.integer((int)1)).executes(ctx -> {
|
||||
ServerLevel level = ((CommandSourceStack)ctx.getSource()).m_81372_();
|
||||
Vec3 pos = Vec3Argument.m_120844_((CommandContext)ctx, (String)"pos");
|
||||
int zone = IntegerArgumentType.getInteger((CommandContext)ctx, (String)"zone");
|
||||
float power = FloatArgumentType.getFloat((CommandContext)ctx, (String)"power");
|
||||
float scale = FloatArgumentType.getFloat((CommandContext)ctx, (String)"scale");
|
||||
int count = IntegerArgumentType.getInteger((CommandContext)ctx, (String)"count");
|
||||
PacketDistributor.TargetPoint targetPoint = new PacketDistributor.TargetPoint(pos.m_7096_(), pos.m_7098_(), pos.m_7094_(), 256.0, level.m_46472_());
|
||||
for (int i = 0; i < count; ++i) {
|
||||
Vec3 motion = new Vec3((level.m_213780_().m_188500_() - 0.5) * 0.5, (level.m_213780_().m_188500_() - 0.5) * 0.5, (level.m_213780_().m_188500_() - 0.5) * 0.5);
|
||||
float centerY = (float)pos.f_82480_;
|
||||
float maxRadius = Math.max(1.0f, power * 2.0f);
|
||||
float heightPercent = 0.0f;
|
||||
PacketHandler.INSTANCE.send(PacketDistributor.NEAR.with(() -> targetPoint), (Object)new SpawnCustomGlowPacket(pos, motion, zone, power, scale, centerY, maxRadius, heightPercent));
|
||||
}
|
||||
return 1;
|
||||
})))))));
|
||||
dispatcher.register((LiteralArgumentBuilder)((LiteralArgumentBuilder)Commands.m_82127_((String)"spawnspark").requires(source -> source.m_6761_(2))).executes(ctx -> {
|
||||
ServerPlayer player = ((CommandSourceStack)ctx.getSource()).m_81375_();
|
||||
ServerLevel level = player.m_284548_();
|
||||
Vec3 pos = player.m_146892_().m_82549_(player.m_20154_().m_82490_(2.0));
|
||||
RandomSource random = level.m_213780_();
|
||||
for (int i = 0; i < 50; ++i) {
|
||||
level.m_8767_((ParticleOptions)((SimpleParticleType)ModParticles.LINE_SPARK.get()), pos.m_7096_(), pos.m_7098_(), pos.m_7094_(), 1, (random.m_188500_() - 0.5) * 2.5, (random.m_188500_() - 0.5) * 2.5, (random.m_188500_() - 0.5) * 2.5, 1.0);
|
||||
}
|
||||
((CommandSourceStack)ctx.getSource()).m_288197_(() -> Component.m_237113_((String)"Spawned 50 juicy sparks!"), true);
|
||||
return 1;
|
||||
}));
|
||||
dispatcher.register((LiteralArgumentBuilder)((LiteralArgumentBuilder)Commands.m_82127_((String)"rescanchunks").requires(source -> source.m_6761_(2))).executes(ctx -> {
|
||||
try {
|
||||
Entity patt5242$temp = ((CommandSourceStack)ctx.getSource()).m_81373_();
|
||||
if (!(patt5242$temp instanceof ServerPlayer)) {
|
||||
((CommandSourceStack)ctx.getSource()).m_81352_((Component)Component.m_237113_((String)"\u00a76[Explosion Overhaul] \u00a7cThis command can only be used by players"));
|
||||
return 0;
|
||||
}
|
||||
ServerPlayer player = (ServerPlayer)patt5242$temp;
|
||||
BlockIndexManager.showRescanPrompt(player);
|
||||
((CommandSourceStack)ctx.getSource()).m_288197_(() -> Component.m_237113_((String)"\u00a76[Explosion Overhaul] \u00a7eShowing rescan prompt..."), false);
|
||||
return 1;
|
||||
}
|
||||
catch (Exception e) {
|
||||
((CommandSourceStack)ctx.getSource()).m_81352_((Component)Component.m_237113_((String)("\u00a76[Explosion Overhaul] \u00a7cFailed to show rescan prompt: " + e.getMessage())));
|
||||
ExplosionOverhaul.LOGGER.error("Failed to execute rescanchunks command", (Throwable)e);
|
||||
return 0;
|
||||
}
|
||||
}));
|
||||
dispatcher.register((LiteralArgumentBuilder)((LiteralArgumentBuilder)Commands.m_82127_((String)"lowpasstest").requires(source -> source.m_6761_(2))).then(Commands.m_82129_((String)"duration", (ArgumentType)IntegerArgumentType.integer((int)1, (int)600)).executes(ctx -> {
|
||||
ServerPlayer player = ((CommandSourceStack)ctx.getSource()).m_81375_();
|
||||
int duration = IntegerArgumentType.getInteger((CommandContext)ctx, (String)"duration");
|
||||
PacketHandler.INSTANCE.send(PacketDistributor.PLAYER.with(() -> player), (Object)new LowPassTestPacket(duration));
|
||||
((CommandSourceStack)ctx.getSource()).m_288197_(() -> Component.m_237113_((String)("Started low-pass test for " + duration + "s")), false);
|
||||
return 1;
|
||||
})));
|
||||
dispatcher.register((LiteralArgumentBuilder)((LiteralArgumentBuilder)Commands.m_82127_((String)"blurtesting").requires(source -> source.m_6761_(2))).then(Commands.m_82129_((String)"duration", (ArgumentType)IntegerArgumentType.integer((int)1, (int)600)).executes(ctx -> {
|
||||
ServerPlayer player = ((CommandSourceStack)ctx.getSource()).m_81375_();
|
||||
int duration = IntegerArgumentType.getInteger((CommandContext)ctx, (String)"duration");
|
||||
PacketHandler.INSTANCE.send(PacketDistributor.PLAYER.with(() -> player), (Object)new BlurTestPacket(duration));
|
||||
((CommandSourceStack)ctx.getSource()).m_288197_(() -> Component.m_237113_((String)("Started blur test for " + duration + "s")), false);
|
||||
return 1;
|
||||
})));
|
||||
dispatcher.register((LiteralArgumentBuilder)((LiteralArgumentBuilder)Commands.m_82127_((String)"testcamerashake").requires(source -> source.m_6761_(2))).then(Commands.m_82129_((String)"duration", (ArgumentType)IntegerArgumentType.integer((int)1, (int)600)).then(Commands.m_82129_((String)"intensity", (ArgumentType)IntegerArgumentType.integer((int)1, (int)100)).executes(ctx -> {
|
||||
ServerPlayer player = ((CommandSourceStack)ctx.getSource()).m_81375_();
|
||||
int duration = IntegerArgumentType.getInteger((CommandContext)ctx, (String)"duration");
|
||||
int intensityPercent = IntegerArgumentType.getInteger((CommandContext)ctx, (String)"intensity");
|
||||
float intensity = (float)intensityPercent / 100.0f;
|
||||
PacketHandler.INSTANCE.send(PacketDistributor.PLAYER.with(() -> player), (Object)new CameraShakeConcussionPacket(duration, intensity));
|
||||
((CommandSourceStack)ctx.getSource()).m_288197_(() -> Component.m_237113_((String)("Started camera shake test for " + duration + "s at " + intensityPercent + "% intensity")), false);
|
||||
return 1;
|
||||
}))));
|
||||
dispatcher.register((LiteralArgumentBuilder)((LiteralArgumentBuilder)Commands.m_82127_((String)"openaltest").requires(source -> source.m_6761_(2))).then(Commands.m_82129_((String)"target", (ArgumentType)StringArgumentType.word()).suggests((ctx, sb) -> SharedSuggestionProvider.m_82970_(Arrays.asList("deafness", "lowpass", "low_pass"), (SuggestionsBuilder)sb)).then(Commands.m_82129_((String)"state", (ArgumentType)StringArgumentType.word()).suggests((ctx, sb) -> SharedSuggestionProvider.m_82970_(Arrays.asList("on", "off", "enable", "disable", "true", "false"), (SuggestionsBuilder)sb)).executes(ctx -> {
|
||||
boolean turnOn;
|
||||
String target = StringArgumentType.getString((CommandContext)ctx, (String)"target").toLowerCase();
|
||||
String state = StringArgumentType.getString((CommandContext)ctx, (String)"state").toLowerCase();
|
||||
boolean bl = turnOn = state.equals("on") || state.equals("enable") || state.equals("true");
|
||||
if (target.equals("deafness") || target.equals("lowpass") || target.equals("low_pass")) {
|
||||
ServerPlayer player = ((CommandSourceStack)ctx.getSource()).m_81375_();
|
||||
PacketHandler.INSTANCE.send(PacketDistributor.PLAYER.with(() -> player), (Object)new OpenALTogglePacket(target, turnOn));
|
||||
((CommandSourceStack)ctx.getSource()).m_288197_(() -> Component.m_237113_((String)("Sent OpenAL toggle to player: " + target + " -> " + (turnOn ? "ON" : "OFF"))), false);
|
||||
return 1;
|
||||
}
|
||||
((CommandSourceStack)ctx.getSource()).m_81352_((Component)Component.m_237113_((String)("Unknown target: " + target + ". Use 'Deafness' or 'LowPass'.")));
|
||||
return 0;
|
||||
}))));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul;
|
||||
|
||||
import com.vinlanx.explosionoverhaul.ModItems;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.world.item.CreativeModeTab;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.ItemLike;
|
||||
import net.neoforged.bus.api.IEventBus;
|
||||
import net.neoforged.neoforge.registries.DeferredRegister;
|
||||
import net.neoforged.neoforge.registries.RegistryObject;
|
||||
|
||||
public class ModCreativeTabs {
|
||||
public static final DeferredRegister<CreativeModeTab> CREATIVE_MODE_TABS = DeferredRegister.create((ResourceKey)Registries.f_279569_, (String)"explosionoverhaul");
|
||||
public static final RegistryObject<CreativeModeTab> MAIN = CREATIVE_MODE_TABS.register("main", () -> CreativeModeTab.builder().m_257737_(() -> new ItemStack((ItemLike)ModItems.MOD_LOGO.get())).m_257941_((Component)Component.m_237115_((String)"itemGroup.explosionoverhaul.main")).m_257501_((parameters, output) -> output.m_246326_((ItemLike)ModItems.VINLANX_THE_LIGHT.get())).m_257652_());
|
||||
|
||||
public static void register(IEventBus eventBus) {
|
||||
CREATIVE_MODE_TABS.register(eventBus);
|
||||
}
|
||||
}
|
||||
24
src/main/java/com/vinlanx/explosionoverhaul/ModItems.java
Normal file
24
src/main/java/com/vinlanx/explosionoverhaul/ModItems.java
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul;
|
||||
|
||||
import com.vinlanx.explosionoverhaul.ModBlocks;
|
||||
import com.vinlanx.explosionoverhaul.VinlanxTheLightItem;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.neoforged.bus.api.IEventBus;
|
||||
import net.neoforged.neoforge.registries.DeferredRegister;
|
||||
import net.neoforged.neoforge.registries.ForgeRegistries;
|
||||
import net.neoforged.neoforge.registries.IForgeRegistry;
|
||||
import net.neoforged.neoforge.registries.RegistryObject;
|
||||
|
||||
public class ModItems {
|
||||
public static final DeferredRegister<Item> ITEMS = DeferredRegister.create((IForgeRegistry)ForgeRegistries.ITEMS, (String)"explosionoverhaul");
|
||||
public static final RegistryObject<Item> VINLANX_THE_LIGHT = ITEMS.register("vinlanx_the_light", () -> new VinlanxTheLightItem((Block)ModBlocks.VINLANX_THE_LIGHT.get(), new Item.Properties()));
|
||||
public static final RegistryObject<Item> MOD_LOGO = ITEMS.register("mod_logo", () -> new Item(new Item.Properties()));
|
||||
|
||||
public static void register(IEventBus eventBus) {
|
||||
ITEMS.register(eventBus);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.vinlanx.explosionoverhaul.CustomGlowParticleOptions;
|
||||
import com.vinlanx.explosionoverhaul.PlasmaParticleOptions;
|
||||
import com.vinlanx.explosionoverhaul.SmokeParticleOptions;
|
||||
import net.minecraft.core.particles.ParticleType;
|
||||
import net.minecraft.core.particles.SimpleParticleType;
|
||||
import net.neoforged.bus.api.IEventBus;
|
||||
import net.neoforged.neoforge.registries.DeferredRegister;
|
||||
import net.neoforged.neoforge.registries.ForgeRegistries;
|
||||
import net.neoforged.neoforge.registries.IForgeRegistry;
|
||||
import net.neoforged.neoforge.registries.RegistryObject;
|
||||
|
||||
public class ModParticles {
|
||||
public static final DeferredRegister<ParticleType<?>> PARTICLE_TYPES = DeferredRegister.create((IForgeRegistry)ForgeRegistries.PARTICLE_TYPES, (String)"explosionoverhaul");
|
||||
public static final RegistryObject<ParticleType<CustomGlowParticleOptions>> CUSTOM_GLOW = PARTICLE_TYPES.register("custom_glow", () -> new ParticleType<CustomGlowParticleOptions>(true, CustomGlowParticleOptions.DESERIALIZER){
|
||||
|
||||
public Codec<CustomGlowParticleOptions> m_7652_() {
|
||||
return CustomGlowParticleOptions.CODEC;
|
||||
}
|
||||
});
|
||||
public static final RegistryObject<ParticleType<PlasmaParticleOptions>> PLASMA = PARTICLE_TYPES.register("plasma", () -> new ParticleType<PlasmaParticleOptions>(false, PlasmaParticleOptions.DESERIALIZER){
|
||||
|
||||
public Codec<PlasmaParticleOptions> m_7652_() {
|
||||
return PlasmaParticleOptions.CODEC;
|
||||
}
|
||||
});
|
||||
public static final RegistryObject<ParticleType<SmokeParticleOptions>> CUSTOM_SMOKE = PARTICLE_TYPES.register("smoke", () -> new ParticleType<SmokeParticleOptions>(false, SmokeParticleOptions.DESERIALIZER){
|
||||
|
||||
public Codec<SmokeParticleOptions> m_7652_() {
|
||||
return SmokeParticleOptions.CODEC;
|
||||
}
|
||||
});
|
||||
public static final RegistryObject<SimpleParticleType> LINE_SPARK = PARTICLE_TYPES.register("line_spark", () -> new SimpleParticleType(true));
|
||||
|
||||
public static void register(IEventBus eventBus) {
|
||||
PARTICLE_TYPES.register(eventBus);
|
||||
}
|
||||
}
|
||||
374
src/main/java/com/vinlanx/explosionoverhaul/ModSounds.java
Normal file
374
src/main/java/com/vinlanx/explosionoverhaul/ModSounds.java
Normal file
@@ -0,0 +1,374 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul;
|
||||
|
||||
import java.util.List;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.sounds.SoundEvent;
|
||||
import net.neoforged.bus.api.IEventBus;
|
||||
import net.neoforged.neoforge.registries.DeferredRegister;
|
||||
import net.neoforged.neoforge.registries.ForgeRegistries;
|
||||
import net.neoforged.neoforge.registries.IForgeRegistry;
|
||||
import net.neoforged.neoforge.registries.RegistryObject;
|
||||
|
||||
public class ModSounds {
|
||||
public static final DeferredRegister<SoundEvent> SOUNDS = DeferredRegister.create((IForgeRegistry)ForgeRegistries.SOUND_EVENTS, (String)"explosionoverhaul");
|
||||
public static final RegistryObject<SoundEvent> BUTTON_SOUND = ModSounds.register("button_sound");
|
||||
public static final RegistryObject<SoundEvent> HEART_LAB = ModSounds.register("lab");
|
||||
public static final RegistryObject<SoundEvent> HEART_DAB = ModSounds.register("dab");
|
||||
public static final RegistryObject<SoundEvent> LOW_SOUND = ModSounds.register("low");
|
||||
public static final RegistryObject<SoundEvent> DUST_SOUND = ModSounds.register("dust");
|
||||
public static final RegistryObject<SoundEvent> FALLING_STONES_SOUND = ModSounds.register("falling_stones");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_CLOSE_POWER_1_1 = ModSounds.register("explode_close_power_1_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_CLOSE_POWER_1_2 = ModSounds.register("explode_close_power_1_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_CLOSE_POWER_1_3 = ModSounds.register("explode_close_power_1_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_CLOSE_POWER_2_1 = ModSounds.register("explode_close_power_2_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_CLOSE_POWER_2_2 = ModSounds.register("explode_close_power_2_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_CLOSE_POWER_2_3 = ModSounds.register("explode_close_power_2_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_CLOSE_POWER_3_1 = ModSounds.register("explode_close_power_3_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_CLOSE_POWER_3_2 = ModSounds.register("explode_close_power_3_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_CLOSE_POWER_3_3 = ModSounds.register("explode_close_power_3_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_CLOSE_POWER_4_1 = ModSounds.register("explode_close_power_4_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_CLOSE_POWER_4_2 = ModSounds.register("explode_close_power_4_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_CLOSE_POWER_4_3 = ModSounds.register("explode_close_power_4_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_CLOSE_POWER_5_1 = ModSounds.register("explode_close_power_5_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_CLOSE_POWER_5_2 = ModSounds.register("explode_close_power_5_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_CLOSE_POWER_5_3 = ModSounds.register("explode_close_power_5_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_CLOSE_POWER_6_1 = ModSounds.register("explode_close_power_6_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_CLOSE_POWER_6_2 = ModSounds.register("explode_close_power_6_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_CLOSE_POWER_6_3 = ModSounds.register("explode_close_power_6_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_CLOSE_POWER_7_1 = ModSounds.register("explode_close_power_7_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_CLOSE_POWER_7_2 = ModSounds.register("explode_close_power_7_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_CLOSE_POWER_7_3 = ModSounds.register("explode_close_power_7_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_POWER_1_1 = ModSounds.register("explode_medium_power_1_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_POWER_1_2 = ModSounds.register("explode_medium_power_1_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_POWER_1_3 = ModSounds.register("explode_medium_power_1_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_POWER_2_1 = ModSounds.register("explode_medium_power_2_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_POWER_2_2 = ModSounds.register("explode_medium_power_2_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_POWER_2_3 = ModSounds.register("explode_medium_power_2_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_POWER_3_1 = ModSounds.register("explode_medium_power_3_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_POWER_3_2 = ModSounds.register("explode_medium_power_3_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_POWER_3_3 = ModSounds.register("explode_medium_power_3_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_POWER_4_1 = ModSounds.register("explode_medium_power_4_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_POWER_4_2 = ModSounds.register("explode_medium_power_4_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_POWER_4_3 = ModSounds.register("explode_medium_power_4_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_POWER_5_1 = ModSounds.register("explode_medium_power_5_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_POWER_5_2 = ModSounds.register("explode_medium_power_5_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_POWER_5_3 = ModSounds.register("explode_medium_power_5_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_POWER_6_1 = ModSounds.register("explode_medium_power_6_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_POWER_6_2 = ModSounds.register("explode_medium_power_6_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_POWER_6_3 = ModSounds.register("explode_medium_power_6_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_POWER_7_1 = ModSounds.register("explode_medium_power_7_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_POWER_7_2 = ModSounds.register("explode_medium_power_7_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_POWER_7_3 = ModSounds.register("explode_medium_power_7_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_CAVE_POWER_1_1 = ModSounds.register("explode_medium_cave_power_1_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_CAVE_POWER_1_2 = ModSounds.register("explode_medium_cave_power_1_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_CAVE_POWER_1_3 = ModSounds.register("explode_medium_cave_power_1_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_CAVE_POWER_2_1 = ModSounds.register("explode_medium_cave_power_2_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_CAVE_POWER_2_2 = ModSounds.register("explode_medium_cave_power_2_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_CAVE_POWER_2_3 = ModSounds.register("explode_medium_cave_power_2_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_CAVE_POWER_3_1 = ModSounds.register("explode_medium_cave_power_3_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_CAVE_POWER_3_2 = ModSounds.register("explode_medium_cave_power_3_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_CAVE_POWER_3_3 = ModSounds.register("explode_medium_cave_power_3_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_CAVE_POWER_4_1 = ModSounds.register("explode_medium_cave_power_4_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_CAVE_POWER_4_2 = ModSounds.register("explode_medium_cave_power_4_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_CAVE_POWER_4_3 = ModSounds.register("explode_medium_cave_power_4_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_CAVE_POWER_5_1 = ModSounds.register("explode_medium_cave_power_5_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_CAVE_POWER_5_2 = ModSounds.register("explode_medium_cave_power_5_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_CAVE_POWER_5_3 = ModSounds.register("explode_medium_cave_power_5_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_CAVE_POWER_6_1 = ModSounds.register("explode_medium_cave_power_6_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_CAVE_POWER_6_2 = ModSounds.register("explode_medium_cave_power_6_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_CAVE_POWER_6_3 = ModSounds.register("explode_medium_cave_power_6_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_CAVE_POWER_7_1 = ModSounds.register("explode_medium_cave_power_7_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_CAVE_POWER_7_2 = ModSounds.register("explode_medium_cave_power_7_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_CAVE_POWER_7_3 = ModSounds.register("explode_medium_cave_power_7_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_TO_HOUSE_POWER_1_1 = ModSounds.register("explode_medium_to_house_power_1_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_TO_HOUSE_POWER_1_2 = ModSounds.register("explode_medium_to_house_power_1_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_TO_HOUSE_POWER_1_3 = ModSounds.register("explode_medium_to_house_power_1_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_TO_HOUSE_POWER_2_1 = ModSounds.register("explode_medium_to_house_power_2_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_TO_HOUSE_POWER_2_2 = ModSounds.register("explode_medium_to_house_power_2_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_TO_HOUSE_POWER_2_3 = ModSounds.register("explode_medium_to_house_power_2_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_TO_HOUSE_POWER_3_1 = ModSounds.register("explode_medium_to_house_power_3_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_TO_HOUSE_POWER_3_2 = ModSounds.register("explode_medium_to_house_power_3_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_TO_HOUSE_POWER_3_3 = ModSounds.register("explode_medium_to_house_power_3_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_TO_HOUSE_POWER_4_1 = ModSounds.register("explode_medium_to_house_power_4_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_TO_HOUSE_POWER_4_2 = ModSounds.register("explode_medium_to_house_power_4_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_TO_HOUSE_POWER_4_3 = ModSounds.register("explode_medium_to_house_power_4_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_TO_HOUSE_POWER_5_1 = ModSounds.register("explode_medium_to_house_power_5_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_TO_HOUSE_POWER_5_2 = ModSounds.register("explode_medium_to_house_power_5_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_TO_HOUSE_POWER_5_3 = ModSounds.register("explode_medium_to_house_power_5_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_TO_HOUSE_POWER_6_1 = ModSounds.register("explode_medium_to_house_power_6_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_TO_HOUSE_POWER_6_2 = ModSounds.register("explode_medium_to_house_power_6_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_TO_HOUSE_POWER_6_3 = ModSounds.register("explode_medium_to_house_power_6_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_TO_HOUSE_POWER_7_1 = ModSounds.register("explode_medium_to_house_power_7_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_TO_HOUSE_POWER_7_2 = ModSounds.register("explode_medium_to_house_power_7_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_TO_HOUSE_POWER_7_3 = ModSounds.register("explode_medium_to_house_power_7_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_UNDERGROUND_POWER_1_1 = ModSounds.register("explode_medium_underground_power_1_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_UNDERGROUND_POWER_1_2 = ModSounds.register("explode_medium_underground_power_1_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_UNDERGROUND_POWER_1_3 = ModSounds.register("explode_medium_underground_power_1_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_UNDERGROUND_POWER_2_1 = ModSounds.register("explode_medium_underground_power_2_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_UNDERGROUND_POWER_2_2 = ModSounds.register("explode_medium_underground_power_2_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_UNDERGROUND_POWER_2_3 = ModSounds.register("explode_medium_underground_power_2_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_UNDERGROUND_POWER_3_1 = ModSounds.register("explode_medium_underground_power_3_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_UNDERGROUND_POWER_3_2 = ModSounds.register("explode_medium_underground_power_3_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_UNDERGROUND_POWER_3_3 = ModSounds.register("explode_medium_underground_power_3_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_UNDERGROUND_POWER_4_1 = ModSounds.register("explode_medium_underground_power_4_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_UNDERGROUND_POWER_4_2 = ModSounds.register("explode_medium_underground_power_4_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_UNDERGROUND_POWER_4_3 = ModSounds.register("explode_medium_underground_power_4_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_UNDERGROUND_POWER_5_1 = ModSounds.register("explode_medium_underground_power_5_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_UNDERGROUND_POWER_5_2 = ModSounds.register("explode_medium_underground_power_5_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_UNDERGROUND_POWER_5_3 = ModSounds.register("explode_medium_underground_power_5_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_UNDERGROUND_POWER_6_1 = ModSounds.register("explode_medium_underground_power_6_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_UNDERGROUND_POWER_6_2 = ModSounds.register("explode_medium_underground_power_6_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_UNDERGROUND_POWER_6_3 = ModSounds.register("explode_medium_underground_power_6_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_UNDERGROUND_POWER_7_1 = ModSounds.register("explode_medium_underground_power_7_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_UNDERGROUND_POWER_7_2 = ModSounds.register("explode_medium_underground_power_7_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_UNDERGROUND_POWER_7_3 = ModSounds.register("explode_medium_underground_power_7_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_CAVE_TO_HOUSE_POWER_1_1 = ModSounds.register("explode_medium_cave_to_house_power_1_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_CAVE_TO_HOUSE_POWER_1_2 = ModSounds.register("explode_medium_cave_to_house_power_1_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_CAVE_TO_HOUSE_POWER_1_3 = ModSounds.register("explode_medium_cave_to_house_power_1_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_CAVE_TO_HOUSE_POWER_2_1 = ModSounds.register("explode_medium_cave_to_house_power_2_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_CAVE_TO_HOUSE_POWER_2_2 = ModSounds.register("explode_medium_cave_to_house_power_2_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_CAVE_TO_HOUSE_POWER_2_3 = ModSounds.register("explode_medium_cave_to_house_power_2_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_CAVE_TO_HOUSE_POWER_3_1 = ModSounds.register("explode_medium_cave_to_house_power_3_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_CAVE_TO_HOUSE_POWER_3_2 = ModSounds.register("explode_medium_cave_to_house_power_3_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_CAVE_TO_HOUSE_POWER_3_3 = ModSounds.register("explode_medium_cave_to_house_power_3_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_CAVE_TO_HOUSE_POWER_4_1 = ModSounds.register("explode_medium_cave_to_house_power_4_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_CAVE_TO_HOUSE_POWER_4_2 = ModSounds.register("explode_medium_cave_to_house_power_4_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_CAVE_TO_HOUSE_POWER_4_3 = ModSounds.register("explode_medium_cave_to_house_power_4_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_CAVE_TO_HOUSE_POWER_5_1 = ModSounds.register("explode_medium_cave_to_house_power_5_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_CAVE_TO_HOUSE_POWER_5_2 = ModSounds.register("explode_medium_cave_to_house_power_5_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_CAVE_TO_HOUSE_POWER_5_3 = ModSounds.register("explode_medium_cave_to_house_power_5_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_CAVE_TO_HOUSE_POWER_6_1 = ModSounds.register("explode_medium_cave_to_house_power_6_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_CAVE_TO_HOUSE_POWER_6_2 = ModSounds.register("explode_medium_cave_to_house_power_6_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_CAVE_TO_HOUSE_POWER_6_3 = ModSounds.register("explode_medium_cave_to_house_power_6_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_CAVE_TO_HOUSE_POWER_7_1 = ModSounds.register("explode_medium_cave_to_house_power_7_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_CAVE_TO_HOUSE_POWER_7_2 = ModSounds.register("explode_medium_cave_to_house_power_7_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_MEDIUM_CAVE_TO_HOUSE_POWER_7_3 = ModSounds.register("explode_medium_cave_to_house_power_7_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_POWER_1_1 = ModSounds.register("explode_far_power_1_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_POWER_1_2 = ModSounds.register("explode_far_power_1_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_POWER_1_3 = ModSounds.register("explode_far_power_1_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_POWER_2_1 = ModSounds.register("explode_far_power_2_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_POWER_2_2 = ModSounds.register("explode_far_power_2_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_POWER_2_3 = ModSounds.register("explode_far_power_2_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_POWER_3_1 = ModSounds.register("explode_far_power_3_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_POWER_3_2 = ModSounds.register("explode_far_power_3_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_POWER_3_3 = ModSounds.register("explode_far_power_3_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_POWER_4_1 = ModSounds.register("explode_far_power_4_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_POWER_4_2 = ModSounds.register("explode_far_power_4_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_POWER_4_3 = ModSounds.register("explode_far_power_4_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_POWER_5_1 = ModSounds.register("explode_far_power_5_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_POWER_5_2 = ModSounds.register("explode_far_power_5_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_POWER_5_3 = ModSounds.register("explode_far_power_5_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_POWER_6_1 = ModSounds.register("explode_far_power_6_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_POWER_6_2 = ModSounds.register("explode_far_power_6_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_POWER_6_3 = ModSounds.register("explode_far_power_6_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_POWER_7_1 = ModSounds.register("explode_far_power_7_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_POWER_7_2 = ModSounds.register("explode_far_power_7_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_POWER_7_3 = ModSounds.register("explode_far_power_7_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_POWER_1_1 = ModSounds.register("explode_superfar_power_1_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_POWER_1_2 = ModSounds.register("explode_superfar_power_1_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_POWER_1_3 = ModSounds.register("explode_superfar_power_1_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_POWER_2_1 = ModSounds.register("explode_superfar_power_2_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_POWER_2_2 = ModSounds.register("explode_superfar_power_2_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_POWER_2_3 = ModSounds.register("explode_superfar_power_2_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_POWER_3_1 = ModSounds.register("explode_superfar_power_3_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_POWER_3_2 = ModSounds.register("explode_superfar_power_3_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_POWER_3_3 = ModSounds.register("explode_superfar_power_3_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_POWER_4_1 = ModSounds.register("explode_superfar_power_4_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_POWER_4_2 = ModSounds.register("explode_superfar_power_4_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_POWER_4_3 = ModSounds.register("explode_superfar_power_4_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_POWER_5_1 = ModSounds.register("explode_superfar_power_5_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_POWER_5_2 = ModSounds.register("explode_superfar_power_5_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_POWER_5_3 = ModSounds.register("explode_superfar_power_5_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_POWER_6_1 = ModSounds.register("explode_superfar_power_6_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_POWER_6_2 = ModSounds.register("explode_superfar_power_6_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_POWER_6_3 = ModSounds.register("explode_superfar_power_6_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_POWER_7_1 = ModSounds.register("explode_superfar_power_7_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_POWER_7_2 = ModSounds.register("explode_superfar_power_7_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_POWER_7_3 = ModSounds.register("explode_superfar_power_7_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_CAVE_POWER_1_1 = ModSounds.register("explode_far_cave_power_1_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_CAVE_POWER_1_2 = ModSounds.register("explode_far_cave_power_1_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_CAVE_POWER_1_3 = ModSounds.register("explode_far_cave_power_1_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_CAVE_POWER_2_1 = ModSounds.register("explode_far_cave_power_2_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_CAVE_POWER_2_2 = ModSounds.register("explode_far_cave_power_2_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_CAVE_POWER_2_3 = ModSounds.register("explode_far_cave_power_2_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_CAVE_POWER_3_1 = ModSounds.register("explode_far_cave_power_3_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_CAVE_POWER_3_2 = ModSounds.register("explode_far_cave_power_3_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_CAVE_POWER_3_3 = ModSounds.register("explode_far_cave_power_3_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_CAVE_POWER_4_1 = ModSounds.register("explode_far_cave_power_4_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_CAVE_POWER_4_2 = ModSounds.register("explode_far_cave_power_4_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_CAVE_POWER_4_3 = ModSounds.register("explode_far_cave_power_4_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_CAVE_POWER_5_1 = ModSounds.register("explode_far_cave_power_5_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_CAVE_POWER_5_2 = ModSounds.register("explode_far_cave_power_5_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_CAVE_POWER_5_3 = ModSounds.register("explode_far_cave_power_5_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_CAVE_POWER_6_1 = ModSounds.register("explode_far_cave_power_6_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_CAVE_POWER_6_2 = ModSounds.register("explode_far_cave_power_6_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_CAVE_POWER_6_3 = ModSounds.register("explode_far_cave_power_6_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_CAVE_POWER_7_1 = ModSounds.register("explode_far_cave_power_7_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_CAVE_POWER_7_2 = ModSounds.register("explode_far_cave_power_7_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_CAVE_POWER_7_3 = ModSounds.register("explode_far_cave_power_7_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_CAVE_POWER_1_1 = ModSounds.register("explode_superfar_cave_power_1_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_CAVE_POWER_1_2 = ModSounds.register("explode_superfar_cave_power_1_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_CAVE_POWER_1_3 = ModSounds.register("explode_superfar_cave_power_1_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_CAVE_POWER_2_1 = ModSounds.register("explode_superfar_cave_power_2_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_CAVE_POWER_2_2 = ModSounds.register("explode_superfar_cave_power_2_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_CAVE_POWER_2_3 = ModSounds.register("explode_superfar_cave_power_2_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_CAVE_POWER_3_1 = ModSounds.register("explode_superfar_cave_power_3_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_CAVE_POWER_3_2 = ModSounds.register("explode_superfar_cave_power_3_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_CAVE_POWER_3_3 = ModSounds.register("explode_superfar_cave_power_3_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_CAVE_POWER_4_1 = ModSounds.register("explode_superfar_cave_power_4_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_CAVE_POWER_4_2 = ModSounds.register("explode_superfar_cave_power_4_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_CAVE_POWER_4_3 = ModSounds.register("explode_superfar_cave_power_4_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_CAVE_POWER_5_1 = ModSounds.register("explode_superfar_cave_power_5_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_CAVE_POWER_5_2 = ModSounds.register("explode_superfar_cave_power_5_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_CAVE_POWER_5_3 = ModSounds.register("explode_superfar_cave_power_5_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_CAVE_POWER_6_1 = ModSounds.register("explode_superfar_cave_power_6_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_CAVE_POWER_6_2 = ModSounds.register("explode_superfar_cave_power_6_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_CAVE_POWER_6_3 = ModSounds.register("explode_superfar_cave_power_6_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_CAVE_POWER_7_1 = ModSounds.register("explode_superfar_cave_power_7_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_CAVE_POWER_7_2 = ModSounds.register("explode_superfar_cave_power_7_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_CAVE_POWER_7_3 = ModSounds.register("explode_superfar_cave_power_7_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_UNDERGROUND_POWER_1_1 = ModSounds.register("explode_far_underground_power_1_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_UNDERGROUND_POWER_1_2 = ModSounds.register("explode_far_underground_power_1_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_UNDERGROUND_POWER_1_3 = ModSounds.register("explode_far_underground_power_1_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_UNDERGROUND_POWER_2_1 = ModSounds.register("explode_far_underground_power_2_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_UNDERGROUND_POWER_2_2 = ModSounds.register("explode_far_underground_power_2_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_UNDERGROUND_POWER_2_3 = ModSounds.register("explode_far_underground_power_2_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_UNDERGROUND_POWER_3_1 = ModSounds.register("explode_far_underground_power_3_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_UNDERGROUND_POWER_3_2 = ModSounds.register("explode_far_underground_power_3_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_UNDERGROUND_POWER_3_3 = ModSounds.register("explode_far_underground_power_3_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_UNDERGROUND_POWER_4_1 = ModSounds.register("explode_far_underground_power_4_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_UNDERGROUND_POWER_4_2 = ModSounds.register("explode_far_underground_power_4_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_UNDERGROUND_POWER_4_3 = ModSounds.register("explode_far_underground_power_4_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_UNDERGROUND_POWER_5_1 = ModSounds.register("explode_far_underground_power_5_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_UNDERGROUND_POWER_5_2 = ModSounds.register("explode_far_underground_power_5_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_UNDERGROUND_POWER_5_3 = ModSounds.register("explode_far_underground_power_5_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_UNDERGROUND_POWER_6_1 = ModSounds.register("explode_far_underground_power_6_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_UNDERGROUND_POWER_6_2 = ModSounds.register("explode_far_underground_power_6_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_UNDERGROUND_POWER_6_3 = ModSounds.register("explode_far_underground_power_6_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_UNDERGROUND_POWER_7_1 = ModSounds.register("explode_far_underground_power_7_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_UNDERGROUND_POWER_7_2 = ModSounds.register("explode_far_underground_power_7_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_UNDERGROUND_POWER_7_3 = ModSounds.register("explode_far_underground_power_7_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_UNDERGROUND_POWER_1_1 = ModSounds.register("explode_superfar_underground_power_1_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_UNDERGROUND_POWER_1_2 = ModSounds.register("explode_superfar_underground_power_1_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_UNDERGROUND_POWER_1_3 = ModSounds.register("explode_superfar_underground_power_1_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_UNDERGROUND_POWER_2_1 = ModSounds.register("explode_superfar_underground_power_2_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_UNDERGROUND_POWER_2_2 = ModSounds.register("explode_superfar_underground_power_2_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_UNDERGROUND_POWER_2_3 = ModSounds.register("explode_superfar_underground_power_2_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_UNDERGROUND_POWER_3_1 = ModSounds.register("explode_superfar_underground_power_3_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_UNDERGROUND_POWER_3_2 = ModSounds.register("explode_superfar_underground_power_3_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_UNDERGROUND_POWER_3_3 = ModSounds.register("explode_superfar_underground_power_3_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_UNDERGROUND_POWER_4_1 = ModSounds.register("explode_superfar_underground_power_4_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_UNDERGROUND_POWER_4_2 = ModSounds.register("explode_superfar_underground_power_4_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_UNDERGROUND_POWER_4_3 = ModSounds.register("explode_superfar_underground_power_4_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_UNDERGROUND_POWER_5_1 = ModSounds.register("explode_superfar_underground_power_5_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_UNDERGROUND_POWER_5_2 = ModSounds.register("explode_superfar_underground_power_5_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_UNDERGROUND_POWER_5_3 = ModSounds.register("explode_superfar_underground_power_5_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_UNDERGROUND_POWER_6_1 = ModSounds.register("explode_superfar_underground_power_6_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_UNDERGROUND_POWER_6_2 = ModSounds.register("explode_superfar_underground_power_6_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_UNDERGROUND_POWER_6_3 = ModSounds.register("explode_superfar_underground_power_6_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_UNDERGROUND_POWER_7_1 = ModSounds.register("explode_superfar_underground_power_7_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_UNDERGROUND_POWER_7_2 = ModSounds.register("explode_superfar_underground_power_7_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_UNDERGROUND_POWER_7_3 = ModSounds.register("explode_superfar_underground_power_7_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_TO_HOUSE_POWER_1_1 = ModSounds.register("explode_far_to_house_power_1_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_TO_HOUSE_POWER_1_2 = ModSounds.register("explode_far_to_house_power_1_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_TO_HOUSE_POWER_1_3 = ModSounds.register("explode_far_to_house_power_1_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_TO_HOUSE_POWER_2_1 = ModSounds.register("explode_far_to_house_power_2_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_TO_HOUSE_POWER_2_2 = ModSounds.register("explode_far_to_house_power_2_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_TO_HOUSE_POWER_2_3 = ModSounds.register("explode_far_to_house_power_2_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_TO_HOUSE_POWER_3_1 = ModSounds.register("explode_far_to_house_power_3_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_TO_HOUSE_POWER_3_2 = ModSounds.register("explode_far_to_house_power_3_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_TO_HOUSE_POWER_3_3 = ModSounds.register("explode_far_to_house_power_3_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_TO_HOUSE_POWER_4_1 = ModSounds.register("explode_far_to_house_power_4_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_TO_HOUSE_POWER_4_2 = ModSounds.register("explode_far_to_house_power_4_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_TO_HOUSE_POWER_4_3 = ModSounds.register("explode_far_to_house_power_4_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_TO_HOUSE_POWER_5_1 = ModSounds.register("explode_far_to_house_power_5_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_TO_HOUSE_POWER_5_2 = ModSounds.register("explode_far_to_house_power_5_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_TO_HOUSE_POWER_5_3 = ModSounds.register("explode_far_to_house_power_5_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_TO_HOUSE_POWER_6_1 = ModSounds.register("explode_far_to_house_power_6_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_TO_HOUSE_POWER_6_2 = ModSounds.register("explode_far_to_house_power_6_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_TO_HOUSE_POWER_6_3 = ModSounds.register("explode_far_to_house_power_6_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_TO_HOUSE_POWER_7_1 = ModSounds.register("explode_far_to_house_power_7_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_TO_HOUSE_POWER_7_2 = ModSounds.register("explode_far_to_house_power_7_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_TO_HOUSE_POWER_7_3 = ModSounds.register("explode_far_to_house_power_7_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_CAVE_TO_HOUSE_POWER_1_1 = ModSounds.register("explode_far_cave_to_house_power_1_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_CAVE_TO_HOUSE_POWER_1_2 = ModSounds.register("explode_far_cave_to_house_power_1_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_CAVE_TO_HOUSE_POWER_1_3 = ModSounds.register("explode_far_cave_to_house_power_1_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_CAVE_TO_HOUSE_POWER_2_1 = ModSounds.register("explode_far_cave_to_house_power_2_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_CAVE_TO_HOUSE_POWER_2_2 = ModSounds.register("explode_far_cave_to_house_power_2_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_CAVE_TO_HOUSE_POWER_2_3 = ModSounds.register("explode_far_cave_to_house_power_2_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_CAVE_TO_HOUSE_POWER_3_1 = ModSounds.register("explode_far_cave_to_house_power_3_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_CAVE_TO_HOUSE_POWER_3_2 = ModSounds.register("explode_far_cave_to_house_power_3_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_CAVE_TO_HOUSE_POWER_3_3 = ModSounds.register("explode_far_cave_to_house_power_3_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_CAVE_TO_HOUSE_POWER_4_1 = ModSounds.register("explode_far_cave_to_house_power_4_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_CAVE_TO_HOUSE_POWER_4_2 = ModSounds.register("explode_far_cave_to_house_power_4_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_CAVE_TO_HOUSE_POWER_4_3 = ModSounds.register("explode_far_cave_to_house_power_4_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_CAVE_TO_HOUSE_POWER_5_1 = ModSounds.register("explode_far_cave_to_house_power_5_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_CAVE_TO_HOUSE_POWER_5_2 = ModSounds.register("explode_far_cave_to_house_power_5_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_CAVE_TO_HOUSE_POWER_5_3 = ModSounds.register("explode_far_cave_to_house_power_5_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_CAVE_TO_HOUSE_POWER_6_1 = ModSounds.register("explode_far_cave_to_house_power_6_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_CAVE_TO_HOUSE_POWER_6_2 = ModSounds.register("explode_far_cave_to_house_power_6_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_CAVE_TO_HOUSE_POWER_6_3 = ModSounds.register("explode_far_cave_to_house_power_6_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_CAVE_TO_HOUSE_POWER_7_1 = ModSounds.register("explode_far_cave_to_house_power_7_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_CAVE_TO_HOUSE_POWER_7_2 = ModSounds.register("explode_far_cave_to_house_power_7_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_FAR_CAVE_TO_HOUSE_POWER_7_3 = ModSounds.register("explode_far_cave_to_house_power_7_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_TO_HOUSE_POWER_1_1 = ModSounds.register("explode_superfar_to_house_power_1_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_TO_HOUSE_POWER_1_2 = ModSounds.register("explode_superfar_to_house_power_1_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_TO_HOUSE_POWER_1_3 = ModSounds.register("explode_superfar_to_house_power_1_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_TO_HOUSE_POWER_2_1 = ModSounds.register("explode_superfar_to_house_power_2_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_TO_HOUSE_POWER_2_2 = ModSounds.register("explode_superfar_to_house_power_2_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_TO_HOUSE_POWER_2_3 = ModSounds.register("explode_superfar_to_house_power_2_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_TO_HOUSE_POWER_3_1 = ModSounds.register("explode_superfar_to_house_power_3_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_TO_HOUSE_POWER_3_2 = ModSounds.register("explode_superfar_to_house_power_3_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_TO_HOUSE_POWER_3_3 = ModSounds.register("explode_superfar_to_house_power_3_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_TO_HOUSE_POWER_4_1 = ModSounds.register("explode_superfar_to_house_power_4_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_TO_HOUSE_POWER_4_2 = ModSounds.register("explode_superfar_to_house_power_4_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_TO_HOUSE_POWER_4_3 = ModSounds.register("explode_superfar_to_house_power_4_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_TO_HOUSE_POWER_5_1 = ModSounds.register("explode_superfar_to_house_power_5_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_TO_HOUSE_POWER_5_2 = ModSounds.register("explode_superfar_to_house_power_5_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_TO_HOUSE_POWER_5_3 = ModSounds.register("explode_superfar_to_house_power_5_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_TO_HOUSE_POWER_6_1 = ModSounds.register("explode_superfar_to_house_power_6_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_TO_HOUSE_POWER_6_2 = ModSounds.register("explode_superfar_to_house_power_6_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_TO_HOUSE_POWER_6_3 = ModSounds.register("explode_superfar_to_house_power_6_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_TO_HOUSE_POWER_7_1 = ModSounds.register("explode_superfar_to_house_power_7_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_TO_HOUSE_POWER_7_2 = ModSounds.register("explode_superfar_to_house_power_7_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_TO_HOUSE_POWER_7_3 = ModSounds.register("explode_superfar_to_house_power_7_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_CAVE_TO_HOUSE_POWER_1_1 = ModSounds.register("explode_superfar_cave_to_house_power_1_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_CAVE_TO_HOUSE_POWER_1_2 = ModSounds.register("explode_superfar_cave_to_house_power_1_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_CAVE_TO_HOUSE_POWER_1_3 = ModSounds.register("explode_superfar_cave_to_house_power_1_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_CAVE_TO_HOUSE_POWER_2_1 = ModSounds.register("explode_superfar_cave_to_house_power_2_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_CAVE_TO_HOUSE_POWER_2_2 = ModSounds.register("explode_superfar_cave_to_house_power_2_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_CAVE_TO_HOUSE_POWER_2_3 = ModSounds.register("explode_superfar_cave_to_house_power_2_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_CAVE_TO_HOUSE_POWER_3_1 = ModSounds.register("explode_superfar_cave_to_house_power_3_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_CAVE_TO_HOUSE_POWER_3_2 = ModSounds.register("explode_superfar_cave_to_house_power_3_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_CAVE_TO_HOUSE_POWER_3_3 = ModSounds.register("explode_superfar_cave_to_house_power_3_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_CAVE_TO_HOUSE_POWER_4_1 = ModSounds.register("explode_superfar_cave_to_house_power_4_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_CAVE_TO_HOUSE_POWER_4_2 = ModSounds.register("explode_superfar_cave_to_house_power_4_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_CAVE_TO_HOUSE_POWER_4_3 = ModSounds.register("explode_superfar_cave_to_house_power_4_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_CAVE_TO_HOUSE_POWER_5_1 = ModSounds.register("explode_superfar_cave_to_house_power_5_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_CAVE_TO_HOUSE_POWER_5_2 = ModSounds.register("explode_superfar_cave_to_house_power_5_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_CAVE_TO_HOUSE_POWER_5_3 = ModSounds.register("explode_superfar_cave_to_house_power_5_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_CAVE_TO_HOUSE_POWER_6_1 = ModSounds.register("explode_superfar_cave_to_house_power_6_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_CAVE_TO_HOUSE_POWER_6_2 = ModSounds.register("explode_superfar_cave_to_house_power_6_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_CAVE_TO_HOUSE_POWER_6_3 = ModSounds.register("explode_superfar_cave_to_house_power_6_3");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_CAVE_TO_HOUSE_POWER_7_1 = ModSounds.register("explode_superfar_cave_to_house_power_7_1");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_CAVE_TO_HOUSE_POWER_7_2 = ModSounds.register("explode_superfar_cave_to_house_power_7_2");
|
||||
public static final RegistryObject<SoundEvent> EXPLODE_SUPERFAR_CAVE_TO_HOUSE_POWER_7_3 = ModSounds.register("explode_superfar_cave_to_house_power_7_3");
|
||||
public static final RegistryObject<SoundEvent> LAMP_FLICKER_SPARK_1 = ModSounds.register("lamp_flicker_spark_1");
|
||||
public static final RegistryObject<SoundEvent> LAMP_FLICKER_SPARK_2 = ModSounds.register("lamp_flicker_spark_2");
|
||||
public static final RegistryObject<SoundEvent> LAMP_FLICKER_SPARK_3 = ModSounds.register("lamp_flicker_spark_3");
|
||||
public static final RegistryObject<SoundEvent> INTRO_MUSIC = ModSounds.register("intro_music");
|
||||
public static final RegistryObject<SoundEvent> INTRO_BOOM = ModSounds.register("intro_boom");
|
||||
public static final RegistryObject<SoundEvent> INTRO_BOOM_2 = ModSounds.register("intro_boom_2");
|
||||
public static final List<RegistryObject<SoundEvent>> LAMP_FLICKER_SOUNDS = List.of(LAMP_FLICKER_SPARK_1, LAMP_FLICKER_SPARK_2, LAMP_FLICKER_SPARK_3);
|
||||
|
||||
private static RegistryObject<SoundEvent> register(String name) {
|
||||
return SOUNDS.register(name, () -> SoundEvent.m_262824_((ResourceLocation)new ResourceLocation("explosionoverhaul", name)));
|
||||
}
|
||||
|
||||
public static void register(IEventBus eventBus) {
|
||||
SOUNDS.register(eventBus);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul;
|
||||
|
||||
import com.vinlanx.explosionoverhaul.client.DeafnessConcussionEffect;
|
||||
import com.vinlanx.explosionoverhaul.client.LowPassConcussionEffect;
|
||||
import java.util.function.Supplier;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.neoforged.api.distmarker.Dist;
|
||||
import net.neoforged.fml.DistExecutor;
|
||||
import net.neoforged.neoforge.network.NetworkEvent;
|
||||
|
||||
public class OpenALTogglePacket {
|
||||
private final String target;
|
||||
private final boolean enabled;
|
||||
|
||||
public OpenALTogglePacket(String target, boolean enabled) {
|
||||
this.target = target;
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
public OpenALTogglePacket(FriendlyByteBuf buf) {
|
||||
this.target = buf.m_130136_(Short.MAX_VALUE);
|
||||
this.enabled = buf.readBoolean();
|
||||
}
|
||||
|
||||
public void encode(FriendlyByteBuf buf) {
|
||||
buf.m_130070_(this.target);
|
||||
buf.writeBoolean(this.enabled);
|
||||
}
|
||||
|
||||
public static OpenALTogglePacket decode(FriendlyByteBuf buf) {
|
||||
return new OpenALTogglePacket(buf);
|
||||
}
|
||||
|
||||
public static void handle(OpenALTogglePacket packet, Supplier<NetworkEvent.Context> ctxSupplier) {
|
||||
NetworkEvent.Context ctx = ctxSupplier.get();
|
||||
ctx.enqueueWork(() -> DistExecutor.unsafeRunWhenOn((Dist)Dist.CLIENT, () -> () -> {
|
||||
String t = packet.target.toLowerCase();
|
||||
if (t.equals("deafness")) {
|
||||
DeafnessConcussionEffect.enabled = packet.enabled;
|
||||
DeafnessConcussionEffect.debugShowChat = packet.enabled;
|
||||
if (DeafnessConcussionEffect.debugShowChat) {
|
||||
Minecraft.m_91087_().f_91074_.m_5661_((Component)Component.m_237113_((String)("Deafness effect set to " + (packet.enabled ? "ON" : "OFF"))), false);
|
||||
}
|
||||
} else if (t.equals("lowpass") || t.equals("low_pass")) {
|
||||
LowPassConcussionEffect.enabled = packet.enabled;
|
||||
LowPassConcussionEffect.debugShowChat = packet.enabled;
|
||||
if (LowPassConcussionEffect.debugShowChat) {
|
||||
Minecraft.m_91087_().f_91074_.m_5661_((Component)Component.m_237113_((String)("LowPass effect set to " + (packet.enabled ? "ON" : "OFF"))), false);
|
||||
}
|
||||
}
|
||||
}));
|
||||
ctx.setPacketHandled(true);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul;
|
||||
|
||||
import com.vinlanx.explosionoverhaul.BlurTestPacket;
|
||||
import com.vinlanx.explosionoverhaul.CameraShakeConcussionPacket;
|
||||
import com.vinlanx.explosionoverhaul.CameraShakePacket;
|
||||
import com.vinlanx.explosionoverhaul.ExplosionVisualsPacket;
|
||||
import com.vinlanx.explosionoverhaul.FlashEffectPacket;
|
||||
import com.vinlanx.explosionoverhaul.LowPassTestPacket;
|
||||
import com.vinlanx.explosionoverhaul.OpenALTogglePacket;
|
||||
import com.vinlanx.explosionoverhaul.PlayTrackedSoundPacket;
|
||||
import com.vinlanx.explosionoverhaul.ScanControlPacket;
|
||||
import com.vinlanx.explosionoverhaul.ScanInfoPacket;
|
||||
import com.vinlanx.explosionoverhaul.ScanLoadControlPacket;
|
||||
import com.vinlanx.explosionoverhaul.ScanLoadPromptPacket;
|
||||
import com.vinlanx.explosionoverhaul.ScanProgressPacket;
|
||||
import com.vinlanx.explosionoverhaul.ScanPromptPacket;
|
||||
import com.vinlanx.explosionoverhaul.SpawnAmbientCaveDustPacket;
|
||||
import com.vinlanx.explosionoverhaul.SpawnCustomGlowPacket;
|
||||
import com.vinlanx.explosionoverhaul.SpawnDustCloudPacket;
|
||||
import com.vinlanx.explosionoverhaul.SpawnLineSparksPacket;
|
||||
import com.vinlanx.explosionoverhaul.SpawnMistCloudPacket;
|
||||
import com.vinlanx.explosionoverhaul.SpawnShockwavePacket;
|
||||
import com.vinlanx.explosionoverhaul.StartConcussionPacket;
|
||||
import com.vinlanx.explosionoverhaul.SuppressExplosionSoundPacket;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.neoforged.neoforge.network.NetworkRegistry;
|
||||
import net.neoforged.neoforge.network.simple.SimpleChannel;
|
||||
|
||||
public class PacketHandler {
|
||||
private static final String PROTOCOL_VERSION = "1";
|
||||
public static final SimpleChannel INSTANCE = NetworkRegistry.newSimpleChannel((ResourceLocation)ResourceLocation.fromNamespaceAndPath((String)"explosionoverhaul", (String)"main"), () -> "1", "1"::equals, "1"::equals);
|
||||
|
||||
public static void register() {
|
||||
int messageId = 0;
|
||||
INSTANCE.registerMessage(messageId++, CameraShakePacket.class, CameraShakePacket::encode, CameraShakePacket::decode, CameraShakePacket::handle);
|
||||
INSTANCE.registerMessage(messageId++, ExplosionVisualsPacket.class, ExplosionVisualsPacket::encode, ExplosionVisualsPacket::decode, ExplosionVisualsPacket::handle);
|
||||
INSTANCE.registerMessage(messageId++, SpawnCustomGlowPacket.class, SpawnCustomGlowPacket::encode, SpawnCustomGlowPacket::decode, SpawnCustomGlowPacket::handle);
|
||||
INSTANCE.registerMessage(messageId++, PlayTrackedSoundPacket.class, PlayTrackedSoundPacket::encode, PlayTrackedSoundPacket::decode, PlayTrackedSoundPacket::handle);
|
||||
INSTANCE.registerMessage(messageId++, SuppressExplosionSoundPacket.class, SuppressExplosionSoundPacket::encode, SuppressExplosionSoundPacket::decode, SuppressExplosionSoundPacket::handle);
|
||||
INSTANCE.registerMessage(messageId++, StartConcussionPacket.class, StartConcussionPacket::encode, StartConcussionPacket::decode, StartConcussionPacket::handle);
|
||||
INSTANCE.registerMessage(messageId++, SpawnShockwavePacket.class, SpawnShockwavePacket::encode, SpawnShockwavePacket::decode, SpawnShockwavePacket::handle);
|
||||
INSTANCE.registerMessage(messageId++, SpawnDustCloudPacket.class, SpawnDustCloudPacket::encode, SpawnDustCloudPacket::decode, SpawnDustCloudPacket::handle);
|
||||
INSTANCE.registerMessage(messageId++, SpawnMistCloudPacket.class, SpawnMistCloudPacket::encode, SpawnMistCloudPacket::decode, SpawnMistCloudPacket::handle);
|
||||
INSTANCE.registerMessage(messageId++, SpawnAmbientCaveDustPacket.class, SpawnAmbientCaveDustPacket::encode, SpawnAmbientCaveDustPacket::decode, SpawnAmbientCaveDustPacket::handle);
|
||||
INSTANCE.registerMessage(messageId++, SpawnLineSparksPacket.class, SpawnLineSparksPacket::encode, SpawnLineSparksPacket::decode, SpawnLineSparksPacket::handle);
|
||||
INSTANCE.registerMessage(messageId++, FlashEffectPacket.class, FlashEffectPacket::encode, FlashEffectPacket::decode, FlashEffectPacket::handle);
|
||||
INSTANCE.registerMessage(messageId++, LowPassTestPacket.class, LowPassTestPacket::encode, LowPassTestPacket::decode, LowPassTestPacket::handle);
|
||||
INSTANCE.registerMessage(messageId++, BlurTestPacket.class, BlurTestPacket::encode, BlurTestPacket::decode, BlurTestPacket::handle);
|
||||
INSTANCE.registerMessage(messageId++, CameraShakeConcussionPacket.class, CameraShakeConcussionPacket::encode, CameraShakeConcussionPacket::decode, CameraShakeConcussionPacket::handle);
|
||||
INSTANCE.registerMessage(messageId++, OpenALTogglePacket.class, OpenALTogglePacket::encode, OpenALTogglePacket::decode, OpenALTogglePacket::handle);
|
||||
INSTANCE.registerMessage(messageId++, ScanProgressPacket.class, ScanProgressPacket::encode, ScanProgressPacket::new, ScanProgressPacket::handle);
|
||||
INSTANCE.registerMessage(messageId++, ScanPromptPacket.class, ScanPromptPacket::encode, ScanPromptPacket::decode, ScanPromptPacket::handle);
|
||||
INSTANCE.registerMessage(messageId++, ScanControlPacket.class, ScanControlPacket::encode, ScanControlPacket::decode, ScanControlPacket::handle);
|
||||
INSTANCE.registerMessage(messageId++, ScanInfoPacket.class, ScanInfoPacket::encode, ScanInfoPacket::decode, ScanInfoPacket::handle);
|
||||
INSTANCE.registerMessage(messageId++, ScanLoadPromptPacket.class, ScanLoadPromptPacket::encode, ScanLoadPromptPacket::decode, ScanLoadPromptPacket::handle);
|
||||
INSTANCE.registerMessage(messageId++, ScanLoadControlPacket.class, ScanLoadControlPacket::encode, ScanLoadControlPacket::decode, ScanLoadControlPacket::handle);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul;
|
||||
|
||||
import com.mojang.brigadier.StringReader;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import com.mojang.datafixers.kinds.App;
|
||||
import com.mojang.datafixers.kinds.Applicative;
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
import com.vinlanx.explosionoverhaul.ModParticles;
|
||||
import java.util.Locale;
|
||||
import net.minecraft.core.particles.ParticleOptions;
|
||||
import net.minecraft.core.particles.ParticleType;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
|
||||
public class PlasmaParticleOptions
|
||||
implements ParticleOptions {
|
||||
public static final Codec<PlasmaParticleOptions> CODEC = RecordCodecBuilder.create(instance -> instance.group((App)Codec.FLOAT.fieldOf("power").forGetter(PlasmaParticleOptions::getPower)).apply((Applicative)instance, PlasmaParticleOptions::new));
|
||||
public static final ParticleOptions.Deserializer<PlasmaParticleOptions> DESERIALIZER = new ParticleOptions.Deserializer<PlasmaParticleOptions>(){
|
||||
|
||||
public PlasmaParticleOptions fromCommand(ParticleType<PlasmaParticleOptions> particleType, StringReader reader) throws CommandSyntaxException {
|
||||
reader.expect(' ');
|
||||
float power = reader.readFloat();
|
||||
return new PlasmaParticleOptions(power);
|
||||
}
|
||||
|
||||
public PlasmaParticleOptions fromNetwork(ParticleType<PlasmaParticleOptions> particleType, FriendlyByteBuf buffer) {
|
||||
return new PlasmaParticleOptions(buffer.readFloat());
|
||||
}
|
||||
};
|
||||
private final float power;
|
||||
|
||||
public PlasmaParticleOptions(float power) {
|
||||
this.power = power;
|
||||
}
|
||||
|
||||
public ParticleType<?> m_6012_() {
|
||||
return (ParticleType)ModParticles.PLASMA.get();
|
||||
}
|
||||
|
||||
public void m_7711_(FriendlyByteBuf buffer) {
|
||||
buffer.writeFloat(this.power);
|
||||
}
|
||||
|
||||
public String m_5942_() {
|
||||
return String.format(Locale.ROOT, "%s %.2f", ModParticles.PLASMA.getId(), Float.valueOf(this.power));
|
||||
}
|
||||
|
||||
public float getPower() {
|
||||
return this.power;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul;
|
||||
|
||||
import com.vinlanx.explosionoverhaul.client.ClientEffects;
|
||||
import java.util.function.Supplier;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.neoforged.api.distmarker.Dist;
|
||||
import net.neoforged.fml.DistExecutor;
|
||||
import net.neoforged.neoforge.network.NetworkEvent;
|
||||
|
||||
public class PlayTrackedSoundPacket {
|
||||
private final Vec3 explosionPos;
|
||||
private final ResourceLocation soundId;
|
||||
private final float volume;
|
||||
private final float pitch;
|
||||
private final long delayTicks;
|
||||
private final boolean isPlayerInHouse;
|
||||
|
||||
public PlayTrackedSoundPacket(Vec3 explosionPos, ResourceLocation soundId, float volume, float pitch, long delayTicks, boolean isPlayerInHouse) {
|
||||
this.explosionPos = explosionPos;
|
||||
this.soundId = soundId;
|
||||
this.volume = volume;
|
||||
this.pitch = pitch;
|
||||
this.delayTicks = delayTicks;
|
||||
this.isPlayerInHouse = isPlayerInHouse;
|
||||
}
|
||||
|
||||
public static void encode(PlayTrackedSoundPacket msg, FriendlyByteBuf buf) {
|
||||
buf.writeDouble(msg.explosionPos.f_82479_);
|
||||
buf.writeDouble(msg.explosionPos.f_82480_);
|
||||
buf.writeDouble(msg.explosionPos.f_82481_);
|
||||
buf.m_130085_(msg.soundId);
|
||||
buf.writeFloat(msg.volume);
|
||||
buf.writeFloat(msg.pitch);
|
||||
buf.m_130103_(msg.delayTicks);
|
||||
buf.writeBoolean(msg.isPlayerInHouse);
|
||||
}
|
||||
|
||||
public static PlayTrackedSoundPacket decode(FriendlyByteBuf buf) {
|
||||
return new PlayTrackedSoundPacket(new Vec3(buf.readDouble(), buf.readDouble(), buf.readDouble()), buf.m_130281_(), buf.readFloat(), buf.readFloat(), buf.m_130258_(), buf.readBoolean());
|
||||
}
|
||||
|
||||
public static void handle(PlayTrackedSoundPacket msg, Supplier<NetworkEvent.Context> ctx) {
|
||||
ctx.get().enqueueWork(() -> DistExecutor.unsafeRunWhenOn((Dist)Dist.CLIENT, () -> () -> ClientEffects.addTrackedSound(msg)));
|
||||
ctx.get().setPacketHandled(true);
|
||||
}
|
||||
|
||||
public Vec3 getExplosionPos() {
|
||||
return this.explosionPos;
|
||||
}
|
||||
|
||||
public ResourceLocation getSoundId() {
|
||||
return this.soundId;
|
||||
}
|
||||
|
||||
public float getVolume() {
|
||||
return this.volume;
|
||||
}
|
||||
|
||||
public float getPitch() {
|
||||
return this.pitch;
|
||||
}
|
||||
|
||||
public long getDelayTicks() {
|
||||
return this.delayTicks;
|
||||
}
|
||||
|
||||
public boolean isPlayerInHouse() {
|
||||
return this.isPlayerInHouse;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,394 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul;
|
||||
|
||||
import com.vinlanx.explosionoverhaul.BlockIndexManager;
|
||||
import com.vinlanx.explosionoverhaul.Config;
|
||||
import com.vinlanx.explosionoverhaul.ModSounds;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.Vec3i;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.sounds.SoundEvent;
|
||||
import net.minecraft.sounds.SoundSource;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
||||
import net.minecraft.world.level.block.state.properties.Property;
|
||||
|
||||
public class RedstoneLampEffects {
|
||||
private static final Map<UUID, List<DelayedLampEffect>> perPlayerDelayedLampEffects = new ConcurrentHashMap<UUID, List<DelayedLampEffect>>();
|
||||
private static final int MIN_INITIAL_FLICKERS = 2;
|
||||
private static final int MAX_INITIAL_FLICKERS = 5;
|
||||
private static final int MIN_FLICKER_PHASE_TICKS = 1;
|
||||
private static final int MAX_FLICKER_PHASE_TICKS = 4;
|
||||
private static final int BASE_MIN_LONG_OFF_TICKS = 20;
|
||||
private static final int FINAL_FLICKER_COUNT = 4;
|
||||
private static final int LAMP_UPDATE_BATCH_SIZE_PER_EFFECT = 25;
|
||||
private static final int LAMP_UPDATE_BUDGET_PER_PLAYER_PER_TICK = 200;
|
||||
private static final int MAX_CONCURRENT_LAMP_GROUPS_PER_PLAYER = 250;
|
||||
|
||||
/*
|
||||
* WARNING - Removed try catching itself - possible behaviour change.
|
||||
*/
|
||||
public static void triggerLampFlicker(ServerLevel level, ServerPlayer player, float explosionPower, long initialDelayTicks, double distanceToExplosionOrigin) {
|
||||
List playerSpecificEffects;
|
||||
if (!((Boolean)Config.COMMON.enableLampFlicker.get()).booleanValue()) {
|
||||
return;
|
||||
}
|
||||
RandomSource random = level.m_213780_();
|
||||
BlockPos playerPos = player.m_20183_();
|
||||
UUID playerId = player.m_20148_();
|
||||
int lampEffectRadius = (Integer)Config.COMMON.lampFlickerSearchRadius.get();
|
||||
long currentMinLongOffTicks = 20L;
|
||||
long currentMaxLongOffTicks = distanceToExplosionOrigin < 500.0 ? 200L : (distanceToExplosionOrigin < 1000.0 ? 100L : 60L);
|
||||
if (currentMinLongOffTicks > currentMaxLongOffTicks) {
|
||||
currentMinLongOffTicks = Math.max(1L, currentMaxLongOffTicks / 2L);
|
||||
}
|
||||
if (currentMaxLongOffTicks <= 0L) {
|
||||
currentMaxLongOffTicks = 1L;
|
||||
}
|
||||
long sharedLongOffDuration = currentMaxLongOffTicks <= currentMinLongOffTicks ? currentMinLongOffTicks : currentMinLongOffTicks + (long)random.m_188503_((int)(currentMaxLongOffTicks - currentMinLongOffTicks + 1L));
|
||||
ArrayList<PotentialLampGroup> potentialLampGroupsFoundThisExplosion = new ArrayList<PotentialLampGroup>();
|
||||
List<BlockPos> allCandidates = BlockIndexManager.getNearby(level, playerPos, lampEffectRadius, BlockIndexManager.BlockType.LAMP);
|
||||
if (allCandidates.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
ArrayList<BlockPos> litLampCandidates = new ArrayList<BlockPos>();
|
||||
for (BlockPos pos : allCandidates) {
|
||||
Object state;
|
||||
if (!level.m_46749_(pos) || !(state = level.m_8055_(pos)).m_60713_(Blocks.f_50261_) || !((Boolean)state.m_61143_((Property)BlockStateProperties.f_61443_)).booleanValue()) continue;
|
||||
litLampCandidates.add(pos);
|
||||
}
|
||||
if (litLampCandidates.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
HashSet<BlockPos> lampsAlreadyInAGroup = new HashSet<BlockPos>();
|
||||
HashSet candidateSet = new HashSet(litLampCandidates);
|
||||
for (BlockPos startPos : litLampCandidates) {
|
||||
BlockState startState;
|
||||
if (lampsAlreadyInAGroup.contains(startPos) || !level.m_46749_(startPos) || !(startState = level.m_8055_(startPos)).m_60713_(Blocks.f_50261_)) continue;
|
||||
ArrayList<BlockPos> currentLampGroupPositions = new ArrayList<BlockPos>();
|
||||
LinkedList<BlockPos> toProcess = new LinkedList<BlockPos>();
|
||||
toProcess.add(startPos);
|
||||
lampsAlreadyInAGroup.add(startPos);
|
||||
while (!toProcess.isEmpty()) {
|
||||
BlockPos lampInQueue = (BlockPos)toProcess.poll();
|
||||
currentLampGroupPositions.add(lampInQueue);
|
||||
for (Direction direction : Direction.values()) {
|
||||
BlockState neighborState;
|
||||
BlockPos neighborPos = lampInQueue.m_5484_(direction, 1);
|
||||
if (!candidateSet.contains(neighborPos) || lampsAlreadyInAGroup.contains(neighborPos) || !level.m_46749_(neighborPos) || !(neighborState = level.m_8055_(neighborPos)).m_60713_(Blocks.f_50261_) || !((Boolean)neighborState.m_61143_((Property)BlockStateProperties.f_61443_)).booleanValue()) continue;
|
||||
lampsAlreadyInAGroup.add(neighborPos);
|
||||
toProcess.add(neighborPos);
|
||||
}
|
||||
}
|
||||
if (currentLampGroupPositions.isEmpty()) continue;
|
||||
double distanceSq = startPos.m_123331_((Vec3i)playerPos);
|
||||
long lampSpecificInitialDelay = initialDelayTicks + (long)random.m_188503_(10);
|
||||
potentialLampGroupsFoundThisExplosion.add(new PotentialLampGroup(startPos, currentLampGroupPositions, true, sharedLongOffDuration, distanceSq, lampSpecificInitialDelay));
|
||||
}
|
||||
if (potentialLampGroupsFoundThisExplosion.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
potentialLampGroupsFoundThisExplosion.sort(Comparator.comparingDouble(PotentialLampGroup::distanceSqToPlayer));
|
||||
List list = playerSpecificEffects = perPlayerDelayedLampEffects.computeIfAbsent(playerId, k -> Collections.synchronizedList(new ArrayList()));
|
||||
synchronized (list) {
|
||||
int currentEffectCountForPlayer = playerSpecificEffects.size();
|
||||
int availableSlotsForThisPlayer = 250 - currentEffectCountForPlayer;
|
||||
if (availableSlotsForThisPlayer <= 0) {
|
||||
return;
|
||||
}
|
||||
int numToAdd = Math.min(potentialLampGroupsFoundThisExplosion.size(), availableSlotsForThisPlayer);
|
||||
for (int i = 0; i < numToAdd; ++i) {
|
||||
PotentialLampGroup chosenGroup = (PotentialLampGroup)potentialLampGroupsFoundThisExplosion.get(i);
|
||||
playerSpecificEffects.add(new DelayedLampEffect(level, chosenGroup.representativePos(), chosenGroup.groupPositions(), chosenGroup.initialDelay(), chosenGroup.originallyLit(), chosenGroup.predeterminedLongOffDuration(), random));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* WARNING - Removed try catching itself - possible behaviour change.
|
||||
*/
|
||||
public static void onServerTick() {
|
||||
for (Map.Entry<UUID, List<DelayedLampEffect>> entry : perPlayerDelayedLampEffects.entrySet()) {
|
||||
List<DelayedLampEffect> playerEffects = entry.getValue();
|
||||
int[] playerBudget = new int[]{200};
|
||||
List<DelayedLampEffect> list = playerEffects;
|
||||
synchronized (list) {
|
||||
Iterator<DelayedLampEffect> effectIterator = playerEffects.iterator();
|
||||
while (effectIterator.hasNext() && playerBudget[0] > 0) {
|
||||
DelayedLampEffect effect = effectIterator.next();
|
||||
if (!effect.tick(playerBudget)) continue;
|
||||
effectIterator.remove();
|
||||
}
|
||||
}
|
||||
if (!playerEffects.isEmpty()) continue;
|
||||
perPlayerDelayedLampEffects.remove(entry.getKey(), playerEffects);
|
||||
}
|
||||
}
|
||||
|
||||
private record PotentialLampGroup(BlockPos representativePos, List<BlockPos> groupPositions, boolean originallyLit, long predeterminedLongOffDuration, double distanceSqToPlayer, long initialDelay) {
|
||||
}
|
||||
|
||||
private static class DelayedLampEffect {
|
||||
public ServerLevel level;
|
||||
public BlockPos representativeLampPos;
|
||||
public List<BlockPos> groupLampPositions;
|
||||
public boolean originallyLit;
|
||||
private final RandomSource random;
|
||||
private LampEffectStage currentStage;
|
||||
private long ticksUntilNextStageAction;
|
||||
private int flickersRemainingInCycle;
|
||||
private long actualLongOffDuration;
|
||||
private int lampUpdateProgressIndex = 0;
|
||||
private boolean currentPhaseTargetLitState;
|
||||
|
||||
public DelayedLampEffect(ServerLevel level, BlockPos representativeLampPos, List<BlockPos> allGroupPositions, long initialDelayTicks, boolean lit, long predeterminedLongOffDuration, RandomSource randomSource) {
|
||||
this.level = level;
|
||||
this.representativeLampPos = representativeLampPos;
|
||||
this.groupLampPositions = new ArrayList<BlockPos>(allGroupPositions);
|
||||
this.originallyLit = lit;
|
||||
this.actualLongOffDuration = predeterminedLongOffDuration;
|
||||
this.random = randomSource;
|
||||
this.currentStage = LampEffectStage.AWAITING_INITIAL_DELAY;
|
||||
this.ticksUntilNextStageAction = initialDelayTicks;
|
||||
}
|
||||
|
||||
private void playFlickerSound() {
|
||||
if (!ModSounds.LAMP_FLICKER_SOUNDS.isEmpty() && !this.groupLampPositions.isEmpty()) {
|
||||
SoundEvent flickerSound = (SoundEvent)ModSounds.LAMP_FLICKER_SOUNDS.get(this.random.m_188503_(ModSounds.LAMP_FLICKER_SOUNDS.size())).get();
|
||||
this.level.m_5594_(null, this.representativeLampPos, flickerSound, SoundSource.BLOCKS, 0.5f, 1.0f + (this.random.m_188501_() - 0.5f) * 0.3f);
|
||||
}
|
||||
}
|
||||
|
||||
private int getRandomPhaseDuration(int minTicks, int maxTicks) {
|
||||
if (minTicks >= maxTicks) {
|
||||
return minTicks;
|
||||
}
|
||||
return this.random.m_188503_(maxTicks - minTicks + 1) + minTicks;
|
||||
}
|
||||
|
||||
private boolean processLampUpdateBatch(int[] budget) {
|
||||
if (this.groupLampPositions.isEmpty()) {
|
||||
this.lampUpdateProgressIndex = 0;
|
||||
return true;
|
||||
}
|
||||
for (int processedInThisEffectCall = 0; this.lampUpdateProgressIndex < this.groupLampPositions.size() && processedInThisEffectCall < 25 && budget[0] > 0; ++processedInThisEffectCall) {
|
||||
boolean currentlyLit;
|
||||
BlockPos posInGroup = this.groupLampPositions.get(this.lampUpdateProgressIndex);
|
||||
BlockState currentBlockState = this.level.m_8055_(posInGroup);
|
||||
if (currentBlockState.m_60713_(Blocks.f_50261_) && (currentlyLit = ((Boolean)currentBlockState.m_61143_((Property)BlockStateProperties.f_61443_)).booleanValue()) != this.currentPhaseTargetLitState) {
|
||||
this.level.m_7731_(posInGroup, (BlockState)currentBlockState.m_61124_((Property)BlockStateProperties.f_61443_, (Comparable)Boolean.valueOf(this.currentPhaseTargetLitState)), 2);
|
||||
budget[0] = budget[0] - 1;
|
||||
}
|
||||
++this.lampUpdateProgressIndex;
|
||||
}
|
||||
if (this.lampUpdateProgressIndex >= this.groupLampPositions.size()) {
|
||||
this.lampUpdateProgressIndex = 0;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean tick(int[] budget) {
|
||||
if (this.currentStage == LampEffectStage.FINISHED) {
|
||||
return true;
|
||||
}
|
||||
--this.ticksUntilNextStageAction;
|
||||
if (this.ticksUntilNextStageAction <= 0L) {
|
||||
LampEffectStage nextStageDecision = this.currentStage;
|
||||
boolean phaseUpdateCompleted = false;
|
||||
switch (this.currentStage) {
|
||||
case AWAITING_INITIAL_DELAY: {
|
||||
this.flickersRemainingInCycle = 2 + this.random.m_188503_(4);
|
||||
nextStageDecision = LampEffectStage.INITIAL_FLICKER_PREPARE_OFF;
|
||||
this.ticksUntilNextStageAction = 1L;
|
||||
break;
|
||||
}
|
||||
case INITIAL_FLICKER_PREPARE_OFF: {
|
||||
this.currentPhaseTargetLitState = false;
|
||||
this.lampUpdateProgressIndex = 0;
|
||||
this.playFlickerSound();
|
||||
nextStageDecision = LampEffectStage.INITIAL_FLICKER_UPDATING_TO_OFF;
|
||||
this.ticksUntilNextStageAction = 1L;
|
||||
break;
|
||||
}
|
||||
case INITIAL_FLICKER_UPDATING_TO_OFF: {
|
||||
phaseUpdateCompleted = this.processLampUpdateBatch(budget);
|
||||
if (phaseUpdateCompleted) {
|
||||
nextStageDecision = LampEffectStage.INITIAL_FLICKER_WAITING_OFF;
|
||||
this.ticksUntilNextStageAction = this.getRandomPhaseDuration(1, 4);
|
||||
break;
|
||||
}
|
||||
this.ticksUntilNextStageAction = 1L;
|
||||
break;
|
||||
}
|
||||
case INITIAL_FLICKER_WAITING_OFF: {
|
||||
nextStageDecision = LampEffectStage.INITIAL_FLICKER_PREPARE_ON;
|
||||
this.ticksUntilNextStageAction = 1L;
|
||||
break;
|
||||
}
|
||||
case INITIAL_FLICKER_PREPARE_ON: {
|
||||
this.currentPhaseTargetLitState = true;
|
||||
this.lampUpdateProgressIndex = 0;
|
||||
this.playFlickerSound();
|
||||
nextStageDecision = LampEffectStage.INITIAL_FLICKER_UPDATING_TO_ON;
|
||||
this.ticksUntilNextStageAction = 1L;
|
||||
break;
|
||||
}
|
||||
case INITIAL_FLICKER_UPDATING_TO_ON: {
|
||||
phaseUpdateCompleted = this.processLampUpdateBatch(budget);
|
||||
if (phaseUpdateCompleted) {
|
||||
--this.flickersRemainingInCycle;
|
||||
if (this.flickersRemainingInCycle > 0) {
|
||||
nextStageDecision = LampEffectStage.INITIAL_FLICKER_WAITING_ON;
|
||||
this.ticksUntilNextStageAction = this.getRandomPhaseDuration(1, 4);
|
||||
break;
|
||||
}
|
||||
nextStageDecision = LampEffectStage.LONG_OFF_PREPARE;
|
||||
this.ticksUntilNextStageAction = 1L;
|
||||
break;
|
||||
}
|
||||
this.ticksUntilNextStageAction = 1L;
|
||||
break;
|
||||
}
|
||||
case INITIAL_FLICKER_WAITING_ON: {
|
||||
nextStageDecision = LampEffectStage.INITIAL_FLICKER_PREPARE_OFF;
|
||||
this.ticksUntilNextStageAction = 1L;
|
||||
break;
|
||||
}
|
||||
case LONG_OFF_PREPARE: {
|
||||
this.currentPhaseTargetLitState = false;
|
||||
this.lampUpdateProgressIndex = 0;
|
||||
nextStageDecision = LampEffectStage.LONG_OFF_UPDATING_TO_OFF;
|
||||
this.ticksUntilNextStageAction = 1L;
|
||||
break;
|
||||
}
|
||||
case LONG_OFF_UPDATING_TO_OFF: {
|
||||
phaseUpdateCompleted = this.processLampUpdateBatch(budget);
|
||||
if (phaseUpdateCompleted) {
|
||||
nextStageDecision = LampEffectStage.LONG_OFF_WAITING;
|
||||
this.ticksUntilNextStageAction = this.actualLongOffDuration;
|
||||
break;
|
||||
}
|
||||
this.ticksUntilNextStageAction = 1L;
|
||||
break;
|
||||
}
|
||||
case LONG_OFF_WAITING: {
|
||||
this.flickersRemainingInCycle = 4;
|
||||
nextStageDecision = LampEffectStage.FINAL_FLICKER_PREPARE_ON;
|
||||
this.ticksUntilNextStageAction = 1L;
|
||||
break;
|
||||
}
|
||||
case FINAL_FLICKER_PREPARE_ON: {
|
||||
this.currentPhaseTargetLitState = true;
|
||||
this.lampUpdateProgressIndex = 0;
|
||||
this.playFlickerSound();
|
||||
nextStageDecision = LampEffectStage.FINAL_FLICKER_UPDATING_TO_ON;
|
||||
this.ticksUntilNextStageAction = 1L;
|
||||
break;
|
||||
}
|
||||
case FINAL_FLICKER_UPDATING_TO_ON: {
|
||||
phaseUpdateCompleted = this.processLampUpdateBatch(budget);
|
||||
if (phaseUpdateCompleted) {
|
||||
nextStageDecision = LampEffectStage.FINAL_FLICKER_WAITING_ON;
|
||||
this.ticksUntilNextStageAction = this.getRandomPhaseDuration(1, 4);
|
||||
break;
|
||||
}
|
||||
this.ticksUntilNextStageAction = 1L;
|
||||
break;
|
||||
}
|
||||
case FINAL_FLICKER_WAITING_ON: {
|
||||
nextStageDecision = LampEffectStage.FINAL_FLICKER_PREPARE_OFF;
|
||||
this.ticksUntilNextStageAction = 1L;
|
||||
break;
|
||||
}
|
||||
case FINAL_FLICKER_PREPARE_OFF: {
|
||||
this.currentPhaseTargetLitState = false;
|
||||
this.lampUpdateProgressIndex = 0;
|
||||
this.playFlickerSound();
|
||||
nextStageDecision = LampEffectStage.FINAL_FLICKER_UPDATING_TO_OFF;
|
||||
this.ticksUntilNextStageAction = 1L;
|
||||
break;
|
||||
}
|
||||
case FINAL_FLICKER_UPDATING_TO_OFF: {
|
||||
phaseUpdateCompleted = this.processLampUpdateBatch(budget);
|
||||
if (phaseUpdateCompleted) {
|
||||
--this.flickersRemainingInCycle;
|
||||
if (this.flickersRemainingInCycle > 0) {
|
||||
nextStageDecision = LampEffectStage.FINAL_FLICKER_WAITING_OFF;
|
||||
this.ticksUntilNextStageAction = this.getRandomPhaseDuration(1, 4);
|
||||
break;
|
||||
}
|
||||
nextStageDecision = LampEffectStage.RESTORING_PREPARE;
|
||||
this.ticksUntilNextStageAction = 1L;
|
||||
break;
|
||||
}
|
||||
this.ticksUntilNextStageAction = 1L;
|
||||
break;
|
||||
}
|
||||
case FINAL_FLICKER_WAITING_OFF: {
|
||||
nextStageDecision = LampEffectStage.FINAL_FLICKER_PREPARE_ON;
|
||||
this.ticksUntilNextStageAction = 1L;
|
||||
break;
|
||||
}
|
||||
case RESTORING_PREPARE: {
|
||||
this.currentPhaseTargetLitState = this.originallyLit;
|
||||
this.lampUpdateProgressIndex = 0;
|
||||
nextStageDecision = LampEffectStage.RESTORING_UPDATING_TO_ORIGINAL;
|
||||
this.ticksUntilNextStageAction = 1L;
|
||||
break;
|
||||
}
|
||||
case RESTORING_UPDATING_TO_ORIGINAL: {
|
||||
phaseUpdateCompleted = this.processLampUpdateBatch(budget);
|
||||
if (phaseUpdateCompleted) {
|
||||
nextStageDecision = LampEffectStage.FINISHED;
|
||||
break;
|
||||
}
|
||||
this.ticksUntilNextStageAction = 1L;
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.currentStage = nextStageDecision;
|
||||
}
|
||||
return this.currentStage == LampEffectStage.FINISHED;
|
||||
}
|
||||
}
|
||||
|
||||
private static enum LampEffectStage {
|
||||
AWAITING_INITIAL_DELAY,
|
||||
INITIAL_FLICKER_PREPARE_OFF,
|
||||
INITIAL_FLICKER_UPDATING_TO_OFF,
|
||||
INITIAL_FLICKER_WAITING_OFF,
|
||||
INITIAL_FLICKER_PREPARE_ON,
|
||||
INITIAL_FLICKER_UPDATING_TO_ON,
|
||||
INITIAL_FLICKER_WAITING_ON,
|
||||
LONG_OFF_PREPARE,
|
||||
LONG_OFF_UPDATING_TO_OFF,
|
||||
LONG_OFF_WAITING,
|
||||
FINAL_FLICKER_PREPARE_ON,
|
||||
FINAL_FLICKER_UPDATING_TO_ON,
|
||||
FINAL_FLICKER_WAITING_ON,
|
||||
FINAL_FLICKER_PREPARE_OFF,
|
||||
FINAL_FLICKER_UPDATING_TO_OFF,
|
||||
FINAL_FLICKER_WAITING_OFF,
|
||||
RESTORING_PREPARE,
|
||||
RESTORING_UPDATING_TO_ORIGINAL,
|
||||
FINISHED;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul;
|
||||
|
||||
import com.vinlanx.explosionoverhaul.BlockIndexManager;
|
||||
import java.util.function.Supplier;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.neoforged.neoforge.network.NetworkEvent;
|
||||
|
||||
public class ScanControlPacket {
|
||||
private final boolean startScan;
|
||||
|
||||
public ScanControlPacket(boolean startScan) {
|
||||
this.startScan = startScan;
|
||||
}
|
||||
|
||||
public static void encode(ScanControlPacket msg, FriendlyByteBuf buf) {
|
||||
buf.writeBoolean(msg.startScan);
|
||||
}
|
||||
|
||||
public static ScanControlPacket decode(FriendlyByteBuf buf) {
|
||||
return new ScanControlPacket(buf.readBoolean());
|
||||
}
|
||||
|
||||
public static void handle(ScanControlPacket msg, Supplier<NetworkEvent.Context> ctx) {
|
||||
ctx.get().enqueueWork(() -> {
|
||||
ServerPlayer player = ((NetworkEvent.Context)ctx.get()).getSender();
|
||||
if (player != null && BlockIndexManager.isPlayerAuthorized(player)) {
|
||||
if (msg.startScan) {
|
||||
BlockIndexManager.startManualScan();
|
||||
} else {
|
||||
BlockIndexManager.cancelManualScan();
|
||||
}
|
||||
}
|
||||
});
|
||||
ctx.get().setPacketHandled(true);
|
||||
}
|
||||
}
|
||||
63
src/main/java/com/vinlanx/explosionoverhaul/ScanInfoHUD.java
Normal file
63
src/main/java/com/vinlanx/explosionoverhaul/ScanInfoHUD.java
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul;
|
||||
|
||||
import com.vinlanx.explosionoverhaul.client.ModKeyMappings;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiGraphics;
|
||||
import net.neoforged.api.distmarker.Dist;
|
||||
import net.neoforged.neoforge.client.event.RenderGuiOverlayEvent;
|
||||
import net.neoforged.bus.api.SubscribeEvent;
|
||||
import net.neoforged.fml.common.Mod;
|
||||
|
||||
@Mod.EventBusSubscriber(value={Dist.CLIENT})
|
||||
public class ScanInfoHUD {
|
||||
private static boolean isVisible = false;
|
||||
|
||||
public static boolean isVisible() {
|
||||
return isVisible;
|
||||
}
|
||||
|
||||
public static void setVisible(boolean visible) {
|
||||
isVisible = visible;
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onRenderGuiOverlay(RenderGuiOverlayEvent.Post event) {
|
||||
if (!isVisible) {
|
||||
return;
|
||||
}
|
||||
Minecraft mc = Minecraft.m_91087_();
|
||||
if (mc.f_91074_ == null) {
|
||||
return;
|
||||
}
|
||||
if (!mc.f_91074_.m_20310_(2) && !mc.m_91091_()) {
|
||||
return;
|
||||
}
|
||||
GuiGraphics guiGraphics = event.getGuiGraphics();
|
||||
String[] infoLines = new String[]{"\u00a76\u00a7lChunk Scanning Information", "", "\u00a7eWhat is chunk scanning?", "\u00a77Chunk scanning analyzes your world to find", "\u00a77and index specific blocks for explosion effects:", "", "\u00a7a\u2022 \u00a77Redstone Lamps \u00a77- for lamp flickering effects", "\u00a7a\u2022 \u00a77Pointed Dripstone \u00a77- for dripstone collapse in caves", "\u00a7a\u2022 \u00a77Glass Blocks \u00a77- for realistic glass breaking", "", "\u00a7eWhy scan chunks?", "\u00a77This allows the mod to create more realistic", "\u00a77explosion effects by knowing where these", "\u00a77blocks are located in your world.", "", "\u00a7ePerformance:", "\u00a77Scanning happens in background and won't", "\u00a77affect your gameplay. You can adjust speed", "\u00a77in mod settings if needed.", "", "\u00a7cPress [" + ModKeyMappings.INFO_SCAN.m_90863_().getString() + "] again to close this info"};
|
||||
int maxWidth = 0;
|
||||
for (String line : infoLines) {
|
||||
int lineWidth = mc.f_91062_.m_92895_(line);
|
||||
if (lineWidth <= maxWidth) continue;
|
||||
maxWidth = lineWidth;
|
||||
}
|
||||
int windowWidth = maxWidth + 20;
|
||||
int windowHeight = infoLines.length * 12 + 20;
|
||||
int screenWidth = mc.m_91268_().m_85445_();
|
||||
int screenHeight = mc.m_91268_().m_85446_();
|
||||
int x = (screenWidth - windowWidth) / 2;
|
||||
int y = (screenHeight - windowHeight) / 2;
|
||||
guiGraphics.m_280509_(x - 5, y - 5, x + windowWidth, y + windowHeight, -536870912);
|
||||
guiGraphics.m_280509_(x - 6, y - 6, x + windowWidth + 1, y - 5, -12303292);
|
||||
guiGraphics.m_280509_(x - 6, y + windowHeight, x + windowWidth + 1, y + windowHeight + 1, -12303292);
|
||||
guiGraphics.m_280509_(x - 6, y - 5, x - 5, y + windowHeight, -12303292);
|
||||
guiGraphics.m_280509_(x + windowWidth, y - 5, x + windowWidth + 1, y + windowHeight, -12303292);
|
||||
for (int i = 0; i < infoLines.length; ++i) {
|
||||
String line = infoLines[i];
|
||||
if (line.isEmpty()) continue;
|
||||
guiGraphics.m_280488_(mc.f_91062_, line, x + 10, y + 10 + i * 12, 0xFFFFFF);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul;
|
||||
|
||||
import com.vinlanx.explosionoverhaul.ScanInfoHUD;
|
||||
import java.util.function.Supplier;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.neoforged.neoforge.network.NetworkEvent;
|
||||
|
||||
public class ScanInfoPacket {
|
||||
private final boolean show;
|
||||
|
||||
public ScanInfoPacket(boolean show) {
|
||||
this.show = show;
|
||||
}
|
||||
|
||||
public void encode(FriendlyByteBuf buf) {
|
||||
buf.writeBoolean(this.show);
|
||||
}
|
||||
|
||||
public static ScanInfoPacket decode(FriendlyByteBuf buf) {
|
||||
boolean show = buf.readBoolean();
|
||||
return new ScanInfoPacket(show);
|
||||
}
|
||||
|
||||
public void handle(Supplier<NetworkEvent.Context> ctx) {
|
||||
ctx.get().enqueueWork(() -> ScanInfoHUD.setVisible(this.show));
|
||||
ctx.get().setPacketHandled(true);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul;
|
||||
|
||||
import com.mojang.blaze3d.platform.InputConstants;
|
||||
import com.vinlanx.explosionoverhaul.PacketHandler;
|
||||
import com.vinlanx.explosionoverhaul.ScanControlPacket;
|
||||
import com.vinlanx.explosionoverhaul.ScanInfoHUD;
|
||||
import com.vinlanx.explosionoverhaul.ScanLoadControlPacket;
|
||||
import com.vinlanx.explosionoverhaul.ScanLoadInfoHUD;
|
||||
import com.vinlanx.explosionoverhaul.ScanLoadPromptHUD;
|
||||
import com.vinlanx.explosionoverhaul.ScanPromptHUD;
|
||||
import com.vinlanx.explosionoverhaul.client.ModKeyMappings;
|
||||
import net.minecraft.client.KeyMapping;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.neoforged.api.distmarker.Dist;
|
||||
import net.neoforged.neoforge.client.event.InputEvent;
|
||||
import net.neoforged.bus.api.SubscribeEvent;
|
||||
import net.neoforged.fml.common.Mod;
|
||||
|
||||
@Mod.EventBusSubscriber(value={Dist.CLIENT})
|
||||
public class ScanKeyHandler {
|
||||
@SubscribeEvent
|
||||
public static void onKeyInput(InputEvent.Key event) {
|
||||
Minecraft mc = Minecraft.m_91087_();
|
||||
if (mc.f_91074_ == null || mc.f_91080_ != null) {
|
||||
return;
|
||||
}
|
||||
if (!mc.f_91074_.m_20310_(2) && !mc.m_91091_()) {
|
||||
return;
|
||||
}
|
||||
if (event.getAction() != 1) {
|
||||
return;
|
||||
}
|
||||
InputConstants.Key key = InputConstants.m_84827_((int)event.getKey(), (int)event.getScanCode());
|
||||
if (ScanLoadPromptHUD.isVisible()) {
|
||||
if (key.equals((Object)ModKeyMappings.ACCEPT_SCAN.getKey())) {
|
||||
PacketHandler.INSTANCE.sendToServer((Object)new ScanLoadControlPacket(true));
|
||||
ScanLoadPromptHUD.setVisible(false);
|
||||
ScanLoadInfoHUD.setVisible(false);
|
||||
if (event.getKey() != 49 && event.getKey() != 50) {
|
||||
ScanKeyHandler.consumeKey(event.getKey());
|
||||
}
|
||||
} else if (key.equals((Object)ModKeyMappings.DECLINE_SCAN.getKey())) {
|
||||
PacketHandler.INSTANCE.sendToServer((Object)new ScanLoadControlPacket(false));
|
||||
ScanLoadPromptHUD.setVisible(false);
|
||||
ScanLoadInfoHUD.setVisible(false);
|
||||
if (event.getKey() != 49 && event.getKey() != 50) {
|
||||
ScanKeyHandler.consumeKey(event.getKey());
|
||||
}
|
||||
} else if (key.equals((Object)ModKeyMappings.INFO_SCAN.getKey())) {
|
||||
boolean currentlyVisible = ScanLoadInfoHUD.isVisible();
|
||||
ScanLoadInfoHUD.setVisible(!currentlyVisible);
|
||||
ScanKeyHandler.consumeKey(event.getKey());
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (ScanPromptHUD.isVisible()) {
|
||||
if (key.equals((Object)ModKeyMappings.ACCEPT_SCAN.getKey())) {
|
||||
PacketHandler.INSTANCE.sendToServer((Object)new ScanControlPacket(true));
|
||||
ScanPromptHUD.setVisible(false);
|
||||
ScanInfoHUD.setVisible(false);
|
||||
if (event.getKey() != 49 && event.getKey() != 50) {
|
||||
ScanKeyHandler.consumeKey(event.getKey());
|
||||
}
|
||||
} else if (key.equals((Object)ModKeyMappings.DECLINE_SCAN.getKey())) {
|
||||
PacketHandler.INSTANCE.sendToServer((Object)new ScanControlPacket(false));
|
||||
ScanPromptHUD.setVisible(false);
|
||||
ScanInfoHUD.setVisible(false);
|
||||
if (event.getKey() != 49 && event.getKey() != 50) {
|
||||
ScanKeyHandler.consumeKey(event.getKey());
|
||||
}
|
||||
} else if (key.equals((Object)ModKeyMappings.INFO_SCAN.getKey())) {
|
||||
boolean currentlyVisible = ScanInfoHUD.isVisible();
|
||||
ScanInfoHUD.setVisible(!currentlyVisible);
|
||||
ScanKeyHandler.consumeKey(event.getKey());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void consumeKey(int keyCode) {
|
||||
Minecraft mc = Minecraft.m_91087_();
|
||||
for (KeyMapping mapping : mc.f_91066_.f_92059_) {
|
||||
if (mapping.getKey().m_84873_() != keyCode) continue;
|
||||
while (mapping.m_90859_()) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul;
|
||||
|
||||
import com.vinlanx.explosionoverhaul.BlockIndexManager;
|
||||
import java.util.function.Supplier;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.neoforged.neoforge.network.NetworkEvent;
|
||||
|
||||
public class ScanLoadControlPacket {
|
||||
private final boolean loadExisting;
|
||||
|
||||
public ScanLoadControlPacket(boolean loadExisting) {
|
||||
this.loadExisting = loadExisting;
|
||||
}
|
||||
|
||||
public static void encode(ScanLoadControlPacket msg, FriendlyByteBuf buf) {
|
||||
buf.writeBoolean(msg.loadExisting);
|
||||
}
|
||||
|
||||
public static ScanLoadControlPacket decode(FriendlyByteBuf buf) {
|
||||
return new ScanLoadControlPacket(buf.readBoolean());
|
||||
}
|
||||
|
||||
public static void handle(ScanLoadControlPacket msg, Supplier<NetworkEvent.Context> ctx) {
|
||||
ctx.get().enqueueWork(() -> {
|
||||
ServerPlayer player = ((NetworkEvent.Context)ctx.get()).getSender();
|
||||
if (player != null && BlockIndexManager.isPlayerAuthorized(player)) {
|
||||
if (msg.loadExisting) {
|
||||
BlockIndexManager.loadExistingData();
|
||||
} else {
|
||||
BlockIndexManager.startNewScan();
|
||||
}
|
||||
}
|
||||
});
|
||||
ctx.get().setPacketHandled(true);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul;
|
||||
|
||||
import com.vinlanx.explosionoverhaul.client.ModKeyMappings;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiGraphics;
|
||||
import net.neoforged.api.distmarker.Dist;
|
||||
import net.neoforged.neoforge.client.event.RenderGuiOverlayEvent;
|
||||
import net.neoforged.bus.api.SubscribeEvent;
|
||||
import net.neoforged.fml.common.Mod;
|
||||
|
||||
@Mod.EventBusSubscriber(value={Dist.CLIENT})
|
||||
public class ScanLoadInfoHUD {
|
||||
private static boolean isVisible = false;
|
||||
|
||||
public static boolean isVisible() {
|
||||
return isVisible;
|
||||
}
|
||||
|
||||
public static void setVisible(boolean visible) {
|
||||
isVisible = visible;
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onRenderGuiOverlay(RenderGuiOverlayEvent.Post event) {
|
||||
if (!isVisible) {
|
||||
return;
|
||||
}
|
||||
Minecraft mc = Minecraft.m_91087_();
|
||||
if (mc.f_91074_ == null) {
|
||||
return;
|
||||
}
|
||||
if (!mc.f_91074_.m_20310_(2) && !mc.m_91091_()) {
|
||||
return;
|
||||
}
|
||||
GuiGraphics guiGraphics = event.getGuiGraphics();
|
||||
String[] infoLines = new String[]{"\u00a76\u00a7lExisting Scan Data Found", "", "\u00a7eThis world has previously scanned block data.", "\u00a7eYou have two options:", "", "\u00a7a\u00a7l[" + ModKeyMappings.ACCEPT_SCAN.m_90863_().getString() + "] Load Data \u00a7r\u00a77- Load existing scan results", "\u00a77\u2022 Instant setup - no waiting time", "\u00a77\u2022 Uses previously found block positions", "\u00a77\u2022 May miss blocks placed after last scan", "\u00a77\u2022 Recommended for established worlds", "", "\u00a7c\u00a7l[" + ModKeyMappings.DECLINE_SCAN.m_90863_().getString() + "] New Scan \u00a7r\u00a77- Perform fresh scan", "\u00a77\u2022 Scans all chunks for current blocks", "\u00a77\u2022 Takes time but finds all blocks", "\u00a77\u2022 Replaces old data with new results", "\u00a77\u2022 Recommended if world changed significantly", "", "\u00a7eNote: \u00a77Block changes are tracked automatically", "\u00a77after loading, so both options work well for", "\u00a77ongoing gameplay.", "", "\u00a7cPress [" + ModKeyMappings.INFO_SCAN.m_90863_().getString() + "] again to close this info"};
|
||||
int maxWidth = 0;
|
||||
for (String line : infoLines) {
|
||||
int lineWidth = mc.f_91062_.m_92895_(line);
|
||||
if (lineWidth <= maxWidth) continue;
|
||||
maxWidth = lineWidth;
|
||||
}
|
||||
int windowWidth = maxWidth + 20;
|
||||
int windowHeight = infoLines.length * 12 + 20;
|
||||
int screenWidth = mc.m_91268_().m_85445_();
|
||||
int screenHeight = mc.m_91268_().m_85446_();
|
||||
int x = (screenWidth - windowWidth) / 2;
|
||||
int y = (screenHeight - windowHeight) / 2;
|
||||
guiGraphics.m_280509_(x - 5, y - 5, x + windowWidth, y + windowHeight, -536870912);
|
||||
guiGraphics.m_280509_(x - 6, y - 6, x + windowWidth + 1, y - 5, -12303292);
|
||||
guiGraphics.m_280509_(x - 6, y + windowHeight, x + windowWidth + 1, y + windowHeight + 1, -12303292);
|
||||
guiGraphics.m_280509_(x - 6, y - 5, x - 5, y + windowHeight, -12303292);
|
||||
guiGraphics.m_280509_(x + windowWidth, y - 5, x + windowWidth + 1, y + windowHeight, -12303292);
|
||||
for (int i = 0; i < infoLines.length; ++i) {
|
||||
String line = infoLines[i];
|
||||
if (line.isEmpty()) continue;
|
||||
guiGraphics.m_280488_(mc.f_91062_, line, x + 10, y + 10 + i * 12, 0xFFFFFF);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul;
|
||||
|
||||
import com.vinlanx.explosionoverhaul.ScanLoadInfoHUD;
|
||||
import com.vinlanx.explosionoverhaul.client.ModKeyMappings;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiGraphics;
|
||||
import net.neoforged.api.distmarker.Dist;
|
||||
import net.neoforged.neoforge.client.event.RenderGuiOverlayEvent;
|
||||
import net.neoforged.bus.api.SubscribeEvent;
|
||||
import net.neoforged.fml.common.Mod;
|
||||
|
||||
@Mod.EventBusSubscriber(value={Dist.CLIENT})
|
||||
public class ScanLoadPromptHUD {
|
||||
private static boolean isVisible = false;
|
||||
|
||||
public static boolean isVisible() {
|
||||
return isVisible;
|
||||
}
|
||||
|
||||
public static void setVisible(boolean visible) {
|
||||
isVisible = visible;
|
||||
if (!visible) {
|
||||
ScanLoadInfoHUD.setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onRenderGuiOverlay(RenderGuiOverlayEvent.Post event) {
|
||||
if (!isVisible) {
|
||||
return;
|
||||
}
|
||||
Minecraft mc = Minecraft.m_91087_();
|
||||
if (mc.f_91074_ == null) {
|
||||
return;
|
||||
}
|
||||
if (!mc.f_91074_.m_20310_(2) && !mc.m_91091_()) {
|
||||
return;
|
||||
}
|
||||
GuiGraphics guiGraphics = event.getGuiGraphics();
|
||||
String promptText = "Found existing scan data for this world!";
|
||||
int x = 10;
|
||||
int y = 10;
|
||||
String key1Text = "[" + ModKeyMappings.ACCEPT_SCAN.m_90863_().getString() + "] = Load Data";
|
||||
String key2Text = "[" + ModKeyMappings.DECLINE_SCAN.m_90863_().getString() + "] = New Scan";
|
||||
String key3Text = "[" + ModKeyMappings.INFO_SCAN.m_90863_().getString() + "] = Info";
|
||||
int maxWidth = Math.max(mc.f_91062_.m_92895_(promptText), mc.f_91062_.m_92895_("Press " + key1Text + ", " + key2Text + ", " + key3Text));
|
||||
guiGraphics.m_280509_(x - 5, y - 5, x + maxWidth + 10, y + 35, Integer.MIN_VALUE);
|
||||
guiGraphics.m_280488_(mc.f_91062_, promptText, x, y, 0xFFFFFF);
|
||||
int currentX = x;
|
||||
int textY = y + 12;
|
||||
guiGraphics.m_280488_(mc.f_91062_, "Press ", currentX, textY, 0xFFFFFF);
|
||||
guiGraphics.m_280488_(mc.f_91062_, key1Text, currentX += mc.f_91062_.m_92895_("Press "), textY, 65280);
|
||||
guiGraphics.m_280488_(mc.f_91062_, ", ", currentX += mc.f_91062_.m_92895_(key1Text), textY, 0xFFFFFF);
|
||||
guiGraphics.m_280488_(mc.f_91062_, key2Text, currentX += mc.f_91062_.m_92895_(", "), textY, 0xFF0000);
|
||||
guiGraphics.m_280488_(mc.f_91062_, ", ", currentX += mc.f_91062_.m_92895_(key2Text), textY, 0xFFFFFF);
|
||||
guiGraphics.m_280488_(mc.f_91062_, key3Text, currentX += mc.f_91062_.m_92895_(", "), textY, 0xFFFF00);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul;
|
||||
|
||||
import com.vinlanx.explosionoverhaul.ScanLoadPromptHUD;
|
||||
import java.util.function.Supplier;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.neoforged.neoforge.network.NetworkEvent;
|
||||
|
||||
public class ScanLoadPromptPacket {
|
||||
private final boolean showPrompt;
|
||||
|
||||
public ScanLoadPromptPacket(boolean showPrompt) {
|
||||
this.showPrompt = showPrompt;
|
||||
}
|
||||
|
||||
public static void encode(ScanLoadPromptPacket msg, FriendlyByteBuf buf) {
|
||||
buf.writeBoolean(msg.showPrompt);
|
||||
}
|
||||
|
||||
public static ScanLoadPromptPacket decode(FriendlyByteBuf buf) {
|
||||
return new ScanLoadPromptPacket(buf.readBoolean());
|
||||
}
|
||||
|
||||
public static void handle(ScanLoadPromptPacket msg, Supplier<NetworkEvent.Context> ctx) {
|
||||
ctx.get().enqueueWork(() -> ScanLoadPromptHUD.setVisible(msg.showPrompt));
|
||||
ctx.get().setPacketHandled(true);
|
||||
}
|
||||
}
|
||||
159
src/main/java/com/vinlanx/explosionoverhaul/ScanProgressHUD.java
Normal file
159
src/main/java/com/vinlanx/explosionoverhaul/ScanProgressHUD.java
Normal file
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul;
|
||||
|
||||
import com.vinlanx.explosionoverhaul.Config;
|
||||
import com.vinlanx.explosionoverhaul.ScanInfoHUD;
|
||||
import com.vinlanx.explosionoverhaul.ScanLoadInfoHUD;
|
||||
import com.vinlanx.explosionoverhaul.ScanLoadPromptHUD;
|
||||
import com.vinlanx.explosionoverhaul.ScanPromptHUD;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.Font;
|
||||
import net.minecraft.client.gui.GuiGraphics;
|
||||
import net.neoforged.api.distmarker.Dist;
|
||||
import net.neoforged.neoforge.client.event.RenderGuiOverlayEvent;
|
||||
import net.neoforged.bus.api.SubscribeEvent;
|
||||
import net.neoforged.fml.common.Mod;
|
||||
|
||||
@Mod.EventBusSubscriber(value={Dist.CLIENT})
|
||||
public class ScanProgressHUD {
|
||||
private static int totalChunks = 0;
|
||||
private static int scannedChunks = 0;
|
||||
private static boolean isComplete = false;
|
||||
private static boolean isVisible = false;
|
||||
private static long hideTime = 0L;
|
||||
private static final long HIDE_DELAY = 4000L;
|
||||
private static int lampsFound = 0;
|
||||
private static int dripstonesFound = 0;
|
||||
private static int glassBlocksFound = 0;
|
||||
private static long startTime = 0L;
|
||||
private static double chunksPerSecond = 0.0;
|
||||
|
||||
public static void updateProgress(int total, int scanned, boolean complete) {
|
||||
ScanProgressHUD.updateProgress(total, scanned, complete, 0, 0, 0);
|
||||
}
|
||||
|
||||
public static void updateProgress(int total, int scanned, boolean complete, int lamps, int dripstones, int glass) {
|
||||
long currentTime;
|
||||
long elapsedTime;
|
||||
if (!((Boolean)Config.COMMON.scan.enableBlockIndexing.get()).booleanValue()) {
|
||||
ScanProgressHUD.reset();
|
||||
return;
|
||||
}
|
||||
totalChunks = total;
|
||||
scannedChunks = scanned;
|
||||
boolean wasComplete = isComplete;
|
||||
isComplete = complete;
|
||||
lampsFound = lamps;
|
||||
dripstonesFound = dripstones;
|
||||
glassBlocksFound = glass;
|
||||
if (scannedChunks == 0 && totalChunks > 0 && !isComplete) {
|
||||
startTime = System.currentTimeMillis();
|
||||
chunksPerSecond = 0.0;
|
||||
}
|
||||
if (scannedChunks > 0 && !isComplete && startTime > 0L && (elapsedTime = (currentTime = System.currentTimeMillis()) - startTime) > 1000L) {
|
||||
chunksPerSecond = (double)scannedChunks / ((double)elapsedTime / 1000.0);
|
||||
}
|
||||
if (total > 0) {
|
||||
if (complete && !wasComplete) {
|
||||
hideTime = System.currentTimeMillis() + 4000L;
|
||||
isVisible = true;
|
||||
} else if (!complete) {
|
||||
isVisible = true;
|
||||
hideTime = 0L;
|
||||
}
|
||||
} else if (total == 0) {
|
||||
ScanProgressHUD.reset();
|
||||
}
|
||||
}
|
||||
|
||||
public static void reset() {
|
||||
totalChunks = 0;
|
||||
scannedChunks = 0;
|
||||
isComplete = false;
|
||||
isVisible = false;
|
||||
hideTime = 0L;
|
||||
lampsFound = 0;
|
||||
dripstonesFound = 0;
|
||||
glassBlocksFound = 0;
|
||||
startTime = 0L;
|
||||
chunksPerSecond = 0.0;
|
||||
}
|
||||
|
||||
private static String getEstimatedTimeRemaining() {
|
||||
if (isComplete) {
|
||||
return "Complete!";
|
||||
}
|
||||
if (totalChunks <= 0 || scannedChunks <= 0 || chunksPerSecond <= 0.1) {
|
||||
return "Calculating...";
|
||||
}
|
||||
int remainingChunks = totalChunks - scannedChunks;
|
||||
double secondsRemaining = (double)remainingChunks / chunksPerSecond;
|
||||
if (secondsRemaining < 0.0) {
|
||||
return "Calculating...";
|
||||
}
|
||||
int minutes = (int)(secondsRemaining / 60.0);
|
||||
int seconds = (int)(secondsRemaining % 60.0);
|
||||
return String.format("ETA: %02d:%02d", minutes, seconds);
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onRenderGuiOverlay(RenderGuiOverlayEvent.Post event) {
|
||||
if (!((Boolean)Config.COMMON.scan.enableBlockIndexing.get()).booleanValue()) {
|
||||
return;
|
||||
}
|
||||
if (!((Boolean)Config.COMMON.scan.showScanProgressHUD.get()).booleanValue()) {
|
||||
return;
|
||||
}
|
||||
if (!isVisible) {
|
||||
return;
|
||||
}
|
||||
if (totalChunks <= 0) {
|
||||
return;
|
||||
}
|
||||
if (ScanPromptHUD.isVisible() || ScanInfoHUD.isVisible() || ScanLoadPromptHUD.isVisible() || ScanLoadInfoHUD.isVisible()) {
|
||||
return;
|
||||
}
|
||||
Minecraft mc = Minecraft.m_91087_();
|
||||
if (mc.f_91074_ == null) {
|
||||
return;
|
||||
}
|
||||
if (!mc.f_91074_.m_20310_(2) && !mc.m_91091_()) {
|
||||
return;
|
||||
}
|
||||
if (isComplete && System.currentTimeMillis() > hideTime) {
|
||||
isVisible = false;
|
||||
return;
|
||||
}
|
||||
GuiGraphics guiGraphics = event.getGuiGraphics();
|
||||
Font font = mc.f_91062_;
|
||||
float progress = totalChunks > 0 ? (float)scannedChunks / (float)totalChunks : 0.0f;
|
||||
int percentage = isComplete ? 100 : Math.round(progress * 100.0f);
|
||||
String statusText = isComplete ? "Scan Complete! (100%)" : String.format("Scanning Chunks: %d%%", percentage);
|
||||
String detailText = String.format("%d / %d chunks", scannedChunks, totalChunks);
|
||||
String blockCountText = String.format("Lamps: %d; Dripstones: %d; Glass: %d", lampsFound, dripstonesFound, glassBlocksFound);
|
||||
String timeText = ScanProgressHUD.getEstimatedTimeRemaining();
|
||||
int x = 10;
|
||||
int y = 10;
|
||||
int textColor = isComplete ? 65280 : 0xFFFFFF;
|
||||
boolean shadowColor = false;
|
||||
int maxWidth = Math.max(Math.max(Math.max(font.m_92895_(statusText), font.m_92895_(detailText)), font.m_92895_(blockCountText)), font.m_92895_(timeText));
|
||||
int bgWidth = Math.max(maxWidth, 100) + 10;
|
||||
int bgHeight = 64;
|
||||
guiGraphics.m_280509_(x - 5, y - 2, x + bgWidth, y + bgHeight, Integer.MIN_VALUE);
|
||||
guiGraphics.m_280488_(font, statusText, x, y, textColor);
|
||||
guiGraphics.m_280488_(font, detailText, x, y + 12, 0xAAAAAA);
|
||||
guiGraphics.m_280488_(font, blockCountText, x, y + 24, 0xCCCCCC);
|
||||
int timeTextColor = isComplete ? 65280 : 0xFFFF00;
|
||||
guiGraphics.m_280488_(font, timeText, x, y + 36, timeTextColor);
|
||||
int barWidth = 100;
|
||||
int barHeight = 4;
|
||||
int barX = x;
|
||||
int barY = y + 52;
|
||||
guiGraphics.m_280509_(barX, barY, barX + barWidth, barY + barHeight, -13421773);
|
||||
int progressWidth = isComplete ? barWidth : (int)((float)barWidth * progress);
|
||||
int barColor = isComplete ? -16711936 : -16733696;
|
||||
guiGraphics.m_280509_(barX, barY, barX + progressWidth, barY + barHeight, barColor);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul;
|
||||
|
||||
import com.vinlanx.explosionoverhaul.ScanProgressHUD;
|
||||
import java.util.function.Supplier;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.neoforged.neoforge.network.NetworkEvent;
|
||||
|
||||
public class ScanProgressPacket {
|
||||
private final int totalChunks;
|
||||
private final int scannedChunks;
|
||||
private final boolean isComplete;
|
||||
private final int lampsFound;
|
||||
private final int dripstonesFound;
|
||||
private final int glassBlocksFound;
|
||||
|
||||
public ScanProgressPacket(int totalChunks, int scannedChunks, boolean isComplete, int lampsFound, int dripstonesFound, int glassBlocksFound) {
|
||||
this.totalChunks = totalChunks;
|
||||
this.scannedChunks = scannedChunks;
|
||||
this.isComplete = isComplete;
|
||||
this.lampsFound = lampsFound;
|
||||
this.dripstonesFound = dripstonesFound;
|
||||
this.glassBlocksFound = glassBlocksFound;
|
||||
}
|
||||
|
||||
public ScanProgressPacket(FriendlyByteBuf buffer) {
|
||||
this.totalChunks = buffer.readInt();
|
||||
this.scannedChunks = buffer.readInt();
|
||||
this.isComplete = buffer.readBoolean();
|
||||
this.lampsFound = buffer.readInt();
|
||||
this.dripstonesFound = buffer.readInt();
|
||||
this.glassBlocksFound = buffer.readInt();
|
||||
}
|
||||
|
||||
public void encode(FriendlyByteBuf buffer) {
|
||||
buffer.writeInt(this.totalChunks);
|
||||
buffer.writeInt(this.scannedChunks);
|
||||
buffer.writeBoolean(this.isComplete);
|
||||
buffer.writeInt(this.lampsFound);
|
||||
buffer.writeInt(this.dripstonesFound);
|
||||
buffer.writeInt(this.glassBlocksFound);
|
||||
}
|
||||
|
||||
public void handle(Supplier<NetworkEvent.Context> contextSupplier) {
|
||||
NetworkEvent.Context context = contextSupplier.get();
|
||||
context.enqueueWork(() -> ScanProgressHUD.updateProgress(this.totalChunks, this.scannedChunks, this.isComplete, this.lampsFound, this.dripstonesFound, this.glassBlocksFound));
|
||||
context.setPacketHandled(true);
|
||||
}
|
||||
|
||||
public int getTotalChunks() {
|
||||
return this.totalChunks;
|
||||
}
|
||||
|
||||
public int getScannedChunks() {
|
||||
return this.scannedChunks;
|
||||
}
|
||||
|
||||
public boolean isComplete() {
|
||||
return this.isComplete;
|
||||
}
|
||||
|
||||
public int getLampsFound() {
|
||||
return this.lampsFound;
|
||||
}
|
||||
|
||||
public int getDripstonesFound() {
|
||||
return this.dripstonesFound;
|
||||
}
|
||||
|
||||
public int getGlassBlocksFound() {
|
||||
return this.glassBlocksFound;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul;
|
||||
|
||||
import com.vinlanx.explosionoverhaul.BlockIndexManager;
|
||||
import com.vinlanx.explosionoverhaul.ScanInfoHUD;
|
||||
import com.vinlanx.explosionoverhaul.client.ModKeyMappings;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiGraphics;
|
||||
import net.neoforged.api.distmarker.Dist;
|
||||
import net.neoforged.neoforge.client.event.RenderGuiOverlayEvent;
|
||||
import net.neoforged.bus.api.SubscribeEvent;
|
||||
import net.neoforged.fml.common.Mod;
|
||||
|
||||
@Mod.EventBusSubscriber(value={Dist.CLIENT})
|
||||
public class ScanPromptHUD {
|
||||
private static boolean isVisible = false;
|
||||
|
||||
public static boolean isVisible() {
|
||||
return isVisible;
|
||||
}
|
||||
|
||||
public static void setVisible(boolean visible) {
|
||||
isVisible = visible;
|
||||
if (!visible) {
|
||||
ScanInfoHUD.setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onRenderGuiOverlay(RenderGuiOverlayEvent.Post event) {
|
||||
if (!isVisible) {
|
||||
return;
|
||||
}
|
||||
Minecraft mc = Minecraft.m_91087_();
|
||||
if (mc.f_91074_ == null) {
|
||||
return;
|
||||
}
|
||||
if (!mc.f_91074_.m_20310_(2) && !mc.m_91091_()) {
|
||||
return;
|
||||
}
|
||||
GuiGraphics guiGraphics = event.getGuiGraphics();
|
||||
String promptText = BlockIndexManager.isRescanMode() ? "Rescan all chunks?" : "Start chunk scanning?";
|
||||
int x = 10;
|
||||
int y = 10;
|
||||
String key1Text = "[" + ModKeyMappings.ACCEPT_SCAN.m_90863_().getString() + "] = Yes";
|
||||
String key2Text = "[" + ModKeyMappings.DECLINE_SCAN.m_90863_().getString() + "] = No";
|
||||
String key3Text = "[" + ModKeyMappings.INFO_SCAN.m_90863_().getString() + "] = Info";
|
||||
int maxWidth = Math.max(mc.f_91062_.m_92895_(promptText), mc.f_91062_.m_92895_("Press " + key1Text + ", " + key2Text + ", " + key3Text));
|
||||
guiGraphics.m_280509_(x - 5, y - 5, x + maxWidth + 10, y + 35, Integer.MIN_VALUE);
|
||||
guiGraphics.m_280488_(mc.f_91062_, promptText, x, y, 0xFFFFFF);
|
||||
int currentX = x;
|
||||
int textY = y + 12;
|
||||
guiGraphics.m_280488_(mc.f_91062_, "Press ", currentX, textY, 0xFFFFFF);
|
||||
guiGraphics.m_280488_(mc.f_91062_, key1Text, currentX += mc.f_91062_.m_92895_("Press "), textY, 65280);
|
||||
guiGraphics.m_280488_(mc.f_91062_, ", ", currentX += mc.f_91062_.m_92895_(key1Text), textY, 0xFFFFFF);
|
||||
guiGraphics.m_280488_(mc.f_91062_, key2Text, currentX += mc.f_91062_.m_92895_(", "), textY, 0xFF0000);
|
||||
guiGraphics.m_280488_(mc.f_91062_, ", ", currentX += mc.f_91062_.m_92895_(key2Text), textY, 0xFFFFFF);
|
||||
guiGraphics.m_280488_(mc.f_91062_, key3Text, currentX += mc.f_91062_.m_92895_(", "), textY, 0xFFFF00);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul;
|
||||
|
||||
import com.vinlanx.explosionoverhaul.ScanPromptHUD;
|
||||
import java.util.function.Supplier;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.neoforged.neoforge.network.NetworkEvent;
|
||||
|
||||
public class ScanPromptPacket {
|
||||
private final boolean showPrompt;
|
||||
|
||||
public ScanPromptPacket(boolean showPrompt) {
|
||||
this.showPrompt = showPrompt;
|
||||
}
|
||||
|
||||
public static void encode(ScanPromptPacket msg, FriendlyByteBuf buf) {
|
||||
buf.writeBoolean(msg.showPrompt);
|
||||
}
|
||||
|
||||
public static ScanPromptPacket decode(FriendlyByteBuf buf) {
|
||||
return new ScanPromptPacket(buf.readBoolean());
|
||||
}
|
||||
|
||||
public static void handle(ScanPromptPacket msg, Supplier<NetworkEvent.Context> ctx) {
|
||||
ctx.get().enqueueWork(() -> ScanPromptHUD.setVisible(msg.showPrompt));
|
||||
ctx.get().setPacketHandled(true);
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul;
|
||||
|
||||
import com.mojang.brigadier.StringReader;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import com.mojang.datafixers.kinds.App;
|
||||
import com.mojang.datafixers.kinds.Applicative;
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
import com.vinlanx.explosionoverhaul.ModParticles;
|
||||
import java.util.Locale;
|
||||
import net.minecraft.client.particle.SpriteSet;
|
||||
import net.minecraft.core.particles.ParticleOptions;
|
||||
import net.minecraft.core.particles.ParticleType;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
|
||||
public class SmokeParticleOptions
|
||||
implements ParticleOptions {
|
||||
public static final Codec<SmokeParticleOptions> CODEC = RecordCodecBuilder.create(instance -> instance.group((App)Codec.FLOAT.fieldOf("scale").forGetter(SmokeParticleOptions::getScale), (App)Codec.INT.fieldOf("lifetime").forGetter(SmokeParticleOptions::getLifetime), (App)Codec.FLOAT.fieldOf("r").forGetter(SmokeParticleOptions::getRed), (App)Codec.FLOAT.fieldOf("g").forGetter(SmokeParticleOptions::getGreen), (App)Codec.FLOAT.fieldOf("b").forGetter(SmokeParticleOptions::getBlue), (App)Codec.FLOAT.fieldOf("a").forGetter(SmokeParticleOptions::getAlpha), (App)Codec.BOOL.fieldOf("isHeavy").forGetter(SmokeParticleOptions::isHeavy), (App)Codec.FLOAT.fieldOf("windSpeed").forGetter(SmokeParticleOptions::getWindSpeed), (App)Codec.FLOAT.fieldOf("heightPercent").forGetter(SmokeParticleOptions::getHeightPercent)).apply((Applicative)instance, (scale, lifetime, r, g, b, a, isHeavy, windSpeed, heightPercent) -> new SmokeParticleOptions(scale.floatValue(), (int)lifetime, r.floatValue(), g.floatValue(), b.floatValue(), a.floatValue(), (boolean)isHeavy, windSpeed.floatValue(), heightPercent.floatValue(), null)));
|
||||
public static final ParticleOptions.Deserializer<SmokeParticleOptions> DESERIALIZER = new ParticleOptions.Deserializer<SmokeParticleOptions>(){
|
||||
|
||||
public SmokeParticleOptions fromCommand(ParticleType<SmokeParticleOptions> particleType, StringReader reader) throws CommandSyntaxException {
|
||||
reader.expect(' ');
|
||||
float scale = reader.readFloat();
|
||||
reader.expect(' ');
|
||||
int lifetime = reader.readInt();
|
||||
reader.expect(' ');
|
||||
float r = reader.readFloat();
|
||||
reader.expect(' ');
|
||||
float g = reader.readFloat();
|
||||
reader.expect(' ');
|
||||
float b = reader.readFloat();
|
||||
reader.expect(' ');
|
||||
float a = reader.readFloat();
|
||||
reader.expect(' ');
|
||||
boolean isHeavy = reader.readBoolean();
|
||||
reader.expect(' ');
|
||||
float windSpeed = reader.readFloat();
|
||||
reader.expect(' ');
|
||||
float heightPercent = reader.readFloat();
|
||||
return new SmokeParticleOptions(scale, lifetime, r, g, b, a, isHeavy, windSpeed, heightPercent, null);
|
||||
}
|
||||
|
||||
public SmokeParticleOptions fromNetwork(ParticleType<SmokeParticleOptions> particleType, FriendlyByteBuf buffer) {
|
||||
return new SmokeParticleOptions(buffer.readFloat(), buffer.readInt(), buffer.readFloat(), buffer.readFloat(), buffer.readFloat(), buffer.readFloat(), buffer.readBoolean(), buffer.readFloat(), buffer.readFloat(), null);
|
||||
}
|
||||
};
|
||||
private final float scale;
|
||||
private final int lifetime;
|
||||
private final float r;
|
||||
private final float g;
|
||||
private final float b;
|
||||
private final float a;
|
||||
private final boolean isHeavy;
|
||||
private final float windSpeed;
|
||||
private final float heightPercent;
|
||||
private final SpriteSet sprites;
|
||||
|
||||
public SmokeParticleOptions(float scale, int lifetime, float r, float g, float b, float a, boolean isHeavy, float windSpeed, float heightPercent, SpriteSet sprites) {
|
||||
this.scale = scale;
|
||||
this.lifetime = lifetime;
|
||||
this.r = r;
|
||||
this.g = g;
|
||||
this.b = b;
|
||||
this.a = a;
|
||||
this.isHeavy = isHeavy;
|
||||
this.windSpeed = windSpeed;
|
||||
this.heightPercent = heightPercent;
|
||||
this.sprites = sprites;
|
||||
}
|
||||
|
||||
public SmokeParticleOptions(float scale, int lifetime, float r, float g, float b, float a, SpriteSet sprites) {
|
||||
this(scale, lifetime, r, g, b, a, false, 0.0f, 0.0f, sprites);
|
||||
}
|
||||
|
||||
public ParticleType<?> m_6012_() {
|
||||
return (ParticleType)ModParticles.CUSTOM_SMOKE.get();
|
||||
}
|
||||
|
||||
public void m_7711_(FriendlyByteBuf buffer) {
|
||||
buffer.writeFloat(this.scale);
|
||||
buffer.writeInt(this.lifetime);
|
||||
buffer.writeFloat(this.r);
|
||||
buffer.writeFloat(this.g);
|
||||
buffer.writeFloat(this.b);
|
||||
buffer.writeFloat(this.a);
|
||||
buffer.writeBoolean(this.isHeavy);
|
||||
buffer.writeFloat(this.windSpeed);
|
||||
buffer.writeFloat(this.heightPercent);
|
||||
}
|
||||
|
||||
public String m_5942_() {
|
||||
return String.format(Locale.ROOT, "%s %.2f %d %.2f %.2f %.2f %.2f %b", ModParticles.CUSTOM_SMOKE.getId(), Float.valueOf(this.scale), this.lifetime, Float.valueOf(this.r), Float.valueOf(this.g), Float.valueOf(this.b), Float.valueOf(this.a), this.isHeavy);
|
||||
}
|
||||
|
||||
public float getScale() {
|
||||
return this.scale;
|
||||
}
|
||||
|
||||
public int getLifetime() {
|
||||
return this.lifetime;
|
||||
}
|
||||
|
||||
public float getRed() {
|
||||
return this.r;
|
||||
}
|
||||
|
||||
public float getGreen() {
|
||||
return this.g;
|
||||
}
|
||||
|
||||
public float getBlue() {
|
||||
return this.b;
|
||||
}
|
||||
|
||||
public float getAlpha() {
|
||||
return this.a;
|
||||
}
|
||||
|
||||
public boolean isHeavy() {
|
||||
return this.isHeavy;
|
||||
}
|
||||
|
||||
public float getWindSpeed() {
|
||||
return this.windSpeed;
|
||||
}
|
||||
|
||||
public float getHeightPercent() {
|
||||
return this.heightPercent;
|
||||
}
|
||||
|
||||
public SpriteSet getSprites() {
|
||||
return this.sprites;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul;
|
||||
|
||||
import com.vinlanx.explosionoverhaul.client.ClientEffects;
|
||||
import java.util.function.Supplier;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.neoforged.api.distmarker.Dist;
|
||||
import net.neoforged.fml.DistExecutor;
|
||||
import net.neoforged.neoforge.network.NetworkEvent;
|
||||
|
||||
public class SpawnAmbientCaveDustPacket {
|
||||
private final float power;
|
||||
|
||||
public SpawnAmbientCaveDustPacket(float power) {
|
||||
this.power = power;
|
||||
}
|
||||
|
||||
public static void encode(SpawnAmbientCaveDustPacket msg, FriendlyByteBuf buf) {
|
||||
buf.writeFloat(msg.power);
|
||||
}
|
||||
|
||||
public static SpawnAmbientCaveDustPacket decode(FriendlyByteBuf buf) {
|
||||
return new SpawnAmbientCaveDustPacket(buf.readFloat());
|
||||
}
|
||||
|
||||
public static void handle(SpawnAmbientCaveDustPacket msg, Supplier<NetworkEvent.Context> ctx) {
|
||||
ctx.get().enqueueWork(() -> DistExecutor.unsafeRunWhenOn((Dist)Dist.CLIENT, () -> () -> ClientEffects.triggerAmbientCaveDust(msg.power)));
|
||||
ctx.get().setPacketHandled(true);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul;
|
||||
|
||||
import com.vinlanx.explosionoverhaul.CustomGlowParticleOptions;
|
||||
import java.util.function.Supplier;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.core.particles.ParticleOptions;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.neoforged.api.distmarker.Dist;
|
||||
import net.neoforged.fml.DistExecutor;
|
||||
import net.neoforged.neoforge.network.NetworkEvent;
|
||||
|
||||
public class SpawnCustomGlowPacket {
|
||||
private final Vec3 pos;
|
||||
private final Vec3 motion;
|
||||
private final int zone;
|
||||
private final float power;
|
||||
private final float scale;
|
||||
private final float centerY;
|
||||
private final float maxRadius;
|
||||
private final float heightPercent;
|
||||
|
||||
public SpawnCustomGlowPacket(Vec3 pos, Vec3 motion, int zone, float power, float scale, float centerY, float maxRadius, float heightPercent) {
|
||||
this.pos = pos;
|
||||
this.motion = motion;
|
||||
this.zone = zone;
|
||||
this.power = power;
|
||||
this.scale = scale;
|
||||
this.centerY = centerY;
|
||||
this.maxRadius = maxRadius;
|
||||
this.heightPercent = heightPercent;
|
||||
}
|
||||
|
||||
public static void encode(SpawnCustomGlowPacket msg, FriendlyByteBuf buf) {
|
||||
buf.writeDouble(msg.pos.f_82479_);
|
||||
buf.writeDouble(msg.pos.f_82480_);
|
||||
buf.writeDouble(msg.pos.f_82481_);
|
||||
buf.writeDouble(msg.motion.f_82479_);
|
||||
buf.writeDouble(msg.motion.f_82480_);
|
||||
buf.writeDouble(msg.motion.f_82481_);
|
||||
buf.writeInt(msg.zone);
|
||||
buf.writeFloat(msg.power);
|
||||
buf.writeFloat(msg.scale);
|
||||
buf.writeFloat(msg.centerY);
|
||||
buf.writeFloat(msg.maxRadius);
|
||||
buf.writeFloat(msg.heightPercent);
|
||||
}
|
||||
|
||||
public static SpawnCustomGlowPacket decode(FriendlyByteBuf buf) {
|
||||
return new SpawnCustomGlowPacket(new Vec3(buf.readDouble(), buf.readDouble(), buf.readDouble()), new Vec3(buf.readDouble(), buf.readDouble(), buf.readDouble()), buf.readInt(), buf.readFloat(), buf.readFloat(), buf.readFloat(), buf.readFloat(), buf.readFloat());
|
||||
}
|
||||
|
||||
public static void handle(SpawnCustomGlowPacket msg, Supplier<NetworkEvent.Context> ctx) {
|
||||
ctx.get().enqueueWork(() -> DistExecutor.unsafeRunWhenOn((Dist)Dist.CLIENT, () -> () -> ClientPacketHandler.handlePacket(msg)));
|
||||
ctx.get().setPacketHandled(true);
|
||||
}
|
||||
|
||||
public static class ClientPacketHandler {
|
||||
public static void handlePacket(SpawnCustomGlowPacket msg) {
|
||||
ClientLevel level = Minecraft.m_91087_().f_91073_;
|
||||
if (level != null) {
|
||||
CustomGlowParticleOptions options = new CustomGlowParticleOptions(msg.zone, msg.power, msg.scale, 0, msg.centerY, msg.maxRadius, msg.heightPercent);
|
||||
level.m_7106_((ParticleOptions)options, msg.pos.f_82479_, msg.pos.f_82480_, msg.pos.f_82481_, msg.motion.f_82479_, msg.motion.f_82480_, msg.motion.f_82481_);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul;
|
||||
|
||||
import com.vinlanx.explosionoverhaul.client.ClientEffects;
|
||||
import java.util.function.Supplier;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.neoforged.api.distmarker.Dist;
|
||||
import net.neoforged.fml.DistExecutor;
|
||||
import net.neoforged.neoforge.network.NetworkEvent;
|
||||
|
||||
public class SpawnDustCloudPacket {
|
||||
private final Vec3 position;
|
||||
private final float power;
|
||||
|
||||
public SpawnDustCloudPacket(Vec3 position, float power) {
|
||||
this.position = position;
|
||||
this.power = power;
|
||||
}
|
||||
|
||||
public static void encode(SpawnDustCloudPacket msg, FriendlyByteBuf buf) {
|
||||
buf.writeDouble(msg.position.f_82479_);
|
||||
buf.writeDouble(msg.position.f_82480_);
|
||||
buf.writeDouble(msg.position.f_82481_);
|
||||
buf.writeFloat(msg.power);
|
||||
}
|
||||
|
||||
public static SpawnDustCloudPacket decode(FriendlyByteBuf buf) {
|
||||
return new SpawnDustCloudPacket(new Vec3(buf.readDouble(), buf.readDouble(), buf.readDouble()), buf.readFloat());
|
||||
}
|
||||
|
||||
public static void handle(SpawnDustCloudPacket msg, Supplier<NetworkEvent.Context> ctx) {
|
||||
ctx.get().enqueueWork(() -> DistExecutor.unsafeRunWhenOn((Dist)Dist.CLIENT, () -> () -> ClientEffects.triggerDustCloud(msg.position, msg.power)));
|
||||
ctx.get().setPacketHandled(true);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul;
|
||||
|
||||
import com.vinlanx.explosionoverhaul.client.ClientEffects;
|
||||
import java.util.function.Supplier;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.neoforged.api.distmarker.Dist;
|
||||
import net.neoforged.fml.DistExecutor;
|
||||
import net.neoforged.neoforge.network.NetworkEvent;
|
||||
|
||||
public class SpawnLineSparksPacket {
|
||||
private final Vec3 position;
|
||||
private final float power;
|
||||
|
||||
public SpawnLineSparksPacket(Vec3 position, float power) {
|
||||
this.position = position;
|
||||
this.power = power;
|
||||
}
|
||||
|
||||
public static void encode(SpawnLineSparksPacket msg, FriendlyByteBuf buf) {
|
||||
buf.writeDouble(msg.position.f_82479_);
|
||||
buf.writeDouble(msg.position.f_82480_);
|
||||
buf.writeDouble(msg.position.f_82481_);
|
||||
buf.writeFloat(msg.power);
|
||||
}
|
||||
|
||||
public static SpawnLineSparksPacket decode(FriendlyByteBuf buf) {
|
||||
return new SpawnLineSparksPacket(new Vec3(buf.readDouble(), buf.readDouble(), buf.readDouble()), buf.readFloat());
|
||||
}
|
||||
|
||||
public static void handle(SpawnLineSparksPacket msg, Supplier<NetworkEvent.Context> ctx) {
|
||||
ctx.get().enqueueWork(() -> DistExecutor.unsafeRunWhenOn((Dist)Dist.CLIENT, () -> () -> ClientEffects.triggerLineSparks(msg.position, msg.power)));
|
||||
ctx.get().setPacketHandled(true);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul;
|
||||
|
||||
import com.vinlanx.explosionoverhaul.client.ClientEffects;
|
||||
import java.util.function.Supplier;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.neoforged.api.distmarker.Dist;
|
||||
import net.neoforged.fml.DistExecutor;
|
||||
import net.neoforged.neoforge.network.NetworkEvent;
|
||||
|
||||
public class SpawnMistCloudPacket {
|
||||
private final Vec3 position;
|
||||
private final float power;
|
||||
|
||||
public SpawnMistCloudPacket(Vec3 position, float power) {
|
||||
this.position = position;
|
||||
this.power = power;
|
||||
}
|
||||
|
||||
public static void encode(SpawnMistCloudPacket msg, FriendlyByteBuf buf) {
|
||||
buf.writeDouble(msg.position.f_82479_);
|
||||
buf.writeDouble(msg.position.f_82480_);
|
||||
buf.writeDouble(msg.position.f_82481_);
|
||||
buf.writeFloat(msg.power);
|
||||
}
|
||||
|
||||
public static SpawnMistCloudPacket decode(FriendlyByteBuf buf) {
|
||||
return new SpawnMistCloudPacket(new Vec3(buf.readDouble(), buf.readDouble(), buf.readDouble()), buf.readFloat());
|
||||
}
|
||||
|
||||
public static void handle(SpawnMistCloudPacket msg, Supplier<NetworkEvent.Context> ctx) {
|
||||
ctx.get().enqueueWork(() -> DistExecutor.unsafeRunWhenOn((Dist)Dist.CLIENT, () -> () -> ClientEffects.triggerMistCloud(msg.position, msg.power)));
|
||||
ctx.get().setPacketHandled(true);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul;
|
||||
|
||||
import com.vinlanx.explosionoverhaul.client.ClientEffects;
|
||||
import java.util.function.Supplier;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.neoforged.api.distmarker.Dist;
|
||||
import net.neoforged.fml.DistExecutor;
|
||||
import net.neoforged.neoforge.network.NetworkEvent;
|
||||
|
||||
public class SpawnShockwavePacket {
|
||||
private final Vec3 position;
|
||||
private final float power;
|
||||
|
||||
public SpawnShockwavePacket(Vec3 position, float power) {
|
||||
this.position = position;
|
||||
this.power = power;
|
||||
}
|
||||
|
||||
public static void encode(SpawnShockwavePacket msg, FriendlyByteBuf buf) {
|
||||
buf.writeDouble(msg.position.f_82479_);
|
||||
buf.writeDouble(msg.position.f_82480_);
|
||||
buf.writeDouble(msg.position.f_82481_);
|
||||
buf.writeFloat(msg.power);
|
||||
}
|
||||
|
||||
public static SpawnShockwavePacket decode(FriendlyByteBuf buf) {
|
||||
return new SpawnShockwavePacket(new Vec3(buf.readDouble(), buf.readDouble(), buf.readDouble()), buf.readFloat());
|
||||
}
|
||||
|
||||
public static void handle(SpawnShockwavePacket msg, Supplier<NetworkEvent.Context> ctx) {
|
||||
ctx.get().enqueueWork(() -> DistExecutor.unsafeRunWhenOn((Dist)Dist.CLIENT, () -> () -> ClientEffects.triggerShockwave(msg.position, msg.power)));
|
||||
ctx.get().setPacketHandled(true);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul;
|
||||
|
||||
import com.vinlanx.explosionoverhaul.client.ConcussionAudioEffect;
|
||||
import java.util.function.Supplier;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.neoforged.api.distmarker.Dist;
|
||||
import net.neoforged.fml.DistExecutor;
|
||||
import net.neoforged.neoforge.network.NetworkEvent;
|
||||
|
||||
public class StartConcussionPacket {
|
||||
private final float power;
|
||||
private final double distance;
|
||||
private final boolean hasDirectLineOfSight;
|
||||
private final boolean explosionInCave;
|
||||
|
||||
public StartConcussionPacket(float power, double distance, boolean hasDirectLineOfSight, boolean explosionInCave) {
|
||||
this.power = power;
|
||||
this.distance = distance;
|
||||
this.hasDirectLineOfSight = hasDirectLineOfSight;
|
||||
this.explosionInCave = explosionInCave;
|
||||
}
|
||||
|
||||
public StartConcussionPacket(FriendlyByteBuf buf) {
|
||||
this.power = buf.readFloat();
|
||||
this.distance = buf.readDouble();
|
||||
this.hasDirectLineOfSight = buf.readBoolean();
|
||||
this.explosionInCave = buf.readBoolean();
|
||||
}
|
||||
|
||||
public void encode(FriendlyByteBuf buf) {
|
||||
buf.writeFloat(this.power);
|
||||
buf.writeDouble(this.distance);
|
||||
buf.writeBoolean(this.hasDirectLineOfSight);
|
||||
buf.writeBoolean(this.explosionInCave);
|
||||
}
|
||||
|
||||
public static StartConcussionPacket decode(FriendlyByteBuf buf) {
|
||||
return new StartConcussionPacket(buf);
|
||||
}
|
||||
|
||||
public float getPower() {
|
||||
return this.power;
|
||||
}
|
||||
|
||||
public double getDistance() {
|
||||
return this.distance;
|
||||
}
|
||||
|
||||
public boolean hasDirectLineOfSight() {
|
||||
return this.hasDirectLineOfSight;
|
||||
}
|
||||
|
||||
public boolean isExplosionInCave() {
|
||||
return this.explosionInCave;
|
||||
}
|
||||
|
||||
public static void handle(StartConcussionPacket packet, Supplier<NetworkEvent.Context> ctxSupplier) {
|
||||
NetworkEvent.Context ctx = ctxSupplier.get();
|
||||
ctx.enqueueWork(() -> DistExecutor.unsafeRunWhenOn((Dist)Dist.CLIENT, () -> () -> ConcussionAudioEffect.start(packet.power, packet.distance, packet.hasDirectLineOfSight, packet.isExplosionInCave())));
|
||||
ctx.setPacketHandled(true);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul;
|
||||
|
||||
import com.vinlanx.explosionoverhaul.ClientSoundHandler;
|
||||
import java.util.function.Supplier;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.neoforged.api.distmarker.Dist;
|
||||
import net.neoforged.fml.DistExecutor;
|
||||
import net.neoforged.neoforge.network.NetworkEvent;
|
||||
|
||||
public class SuppressExplosionSoundPacket {
|
||||
private final float power;
|
||||
|
||||
public SuppressExplosionSoundPacket(float power) {
|
||||
this.power = power;
|
||||
}
|
||||
|
||||
public static void encode(SuppressExplosionSoundPacket msg, FriendlyByteBuf buf) {
|
||||
buf.writeFloat(msg.power);
|
||||
}
|
||||
|
||||
public static SuppressExplosionSoundPacket decode(FriendlyByteBuf buf) {
|
||||
return new SuppressExplosionSoundPacket(buf.readFloat());
|
||||
}
|
||||
|
||||
public static void handle(SuppressExplosionSoundPacket msg, Supplier<NetworkEvent.Context> ctx) {
|
||||
ctx.get().enqueueWork(() -> DistExecutor.unsafeRunWhenOn((Dist)Dist.CLIENT, () -> () -> ClientSoundHandler.setSuppressVanillaExplosionSound(true, 10)));
|
||||
ctx.get().setPacketHandled(true);
|
||||
}
|
||||
|
||||
public float getPower() {
|
||||
return this.power;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul;
|
||||
|
||||
import com.vinlanx.explosionoverhaul.VinlanxTheLightBlockEntity;
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.item.context.BlockPlaceContext;
|
||||
import net.minecraft.world.level.block.BaseEntityBlock;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.HorizontalDirectionalBlock;
|
||||
import net.minecraft.world.level.block.Mirror;
|
||||
import net.minecraft.world.level.block.RenderShape;
|
||||
import net.minecraft.world.level.block.Rotation;
|
||||
import net.minecraft.world.level.block.SoundType;
|
||||
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.StateDefinition;
|
||||
import net.minecraft.world.level.block.state.properties.DirectionProperty;
|
||||
import net.minecraft.world.level.block.state.properties.Property;
|
||||
import net.minecraft.world.level.material.MapColor;
|
||||
|
||||
public class VinlanxTheLightBlock
|
||||
extends BaseEntityBlock {
|
||||
public static final DirectionProperty FACING = HorizontalDirectionalBlock.f_54117_;
|
||||
|
||||
public VinlanxTheLightBlock(BlockBehaviour.Properties properties) {
|
||||
super(properties);
|
||||
this.m_49959_((BlockState)((BlockState)this.f_49792_.m_61090_()).m_61124_((Property)FACING, (Comparable)Direction.NORTH));
|
||||
}
|
||||
|
||||
public static BlockBehaviour.Properties defaultProperties() {
|
||||
return BlockBehaviour.Properties.m_284310_().m_284180_(MapColor.f_283811_).m_60978_(2.5f).m_60955_().m_60918_(SoundType.f_154654_).m_60953_(state -> 12);
|
||||
}
|
||||
|
||||
public RenderShape m_7514_(BlockState state) {
|
||||
return RenderShape.ENTITYBLOCK_ANIMATED;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public BlockEntity m_142194_(BlockPos pos, BlockState state) {
|
||||
return new VinlanxTheLightBlockEntity(pos, state);
|
||||
}
|
||||
|
||||
public BlockState m_5573_(BlockPlaceContext context) {
|
||||
Direction direction = context.m_8125_();
|
||||
return (BlockState)this.m_49966_().m_61124_((Property)FACING, (Comparable)direction);
|
||||
}
|
||||
|
||||
public BlockState m_6843_(BlockState state, Rotation rotation) {
|
||||
return (BlockState)state.m_61124_((Property)FACING, (Comparable)rotation.m_55954_((Direction)state.m_61143_((Property)FACING)));
|
||||
}
|
||||
|
||||
public BlockState m_6943_(BlockState state, Mirror mirror) {
|
||||
return state.m_60717_(mirror.m_54846_((Direction)state.m_61143_((Property)FACING)));
|
||||
}
|
||||
|
||||
protected void m_7926_(StateDefinition.Builder<Block, BlockState> builder) {
|
||||
builder.m_61104_(new Property[]{FACING});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul;
|
||||
|
||||
import com.vinlanx.explosionoverhaul.ModBlockEntities;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import software.bernie.geckolib.animatable.GeoBlockEntity;
|
||||
import software.bernie.geckolib.core.animatable.GeoAnimatable;
|
||||
import software.bernie.geckolib.core.animatable.instance.AnimatableInstanceCache;
|
||||
import software.bernie.geckolib.core.animation.AnimatableManager;
|
||||
import software.bernie.geckolib.util.GeckoLibUtil;
|
||||
|
||||
public class VinlanxTheLightBlockEntity
|
||||
extends BlockEntity
|
||||
implements GeoBlockEntity {
|
||||
private final AnimatableInstanceCache cache = GeckoLibUtil.createInstanceCache((GeoAnimatable)this);
|
||||
|
||||
public VinlanxTheLightBlockEntity(BlockPos pos, BlockState state) {
|
||||
super((BlockEntityType)ModBlockEntities.VINLANX_THE_LIGHT.get(), pos, state);
|
||||
}
|
||||
|
||||
public void registerControllers(AnimatableManager.ControllerRegistrar controllers) {
|
||||
}
|
||||
|
||||
public AnimatableInstanceCache getAnimatableInstanceCache() {
|
||||
return this.cache;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul;
|
||||
|
||||
import com.vinlanx.explosionoverhaul.VinlanxTheLightItemRenderer;
|
||||
import java.util.function.Consumer;
|
||||
import net.minecraft.client.renderer.BlockEntityWithoutLevelRenderer;
|
||||
import net.minecraft.world.item.BlockItem;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.neoforged.neoforge.client.extensions.common.IClientItemExtensions;
|
||||
import software.bernie.geckolib.animatable.GeoItem;
|
||||
import software.bernie.geckolib.core.animatable.GeoAnimatable;
|
||||
import software.bernie.geckolib.core.animatable.instance.AnimatableInstanceCache;
|
||||
import software.bernie.geckolib.core.animation.AnimatableManager;
|
||||
import software.bernie.geckolib.util.GeckoLibUtil;
|
||||
|
||||
public class VinlanxTheLightItem
|
||||
extends BlockItem
|
||||
implements GeoItem {
|
||||
private final AnimatableInstanceCache cache = GeckoLibUtil.createInstanceCache((GeoAnimatable)this);
|
||||
|
||||
public VinlanxTheLightItem(Block block, Item.Properties properties) {
|
||||
super(block, properties);
|
||||
}
|
||||
|
||||
public void registerControllers(AnimatableManager.ControllerRegistrar controllers) {
|
||||
}
|
||||
|
||||
public void initializeClient(Consumer<IClientItemExtensions> consumer) {
|
||||
consumer.accept(new IClientItemExtensions(){
|
||||
private final VinlanxTheLightItemRenderer renderer = new VinlanxTheLightItemRenderer();
|
||||
|
||||
public BlockEntityWithoutLevelRenderer getCustomRenderer() {
|
||||
return this.renderer;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public AnimatableInstanceCache getAnimatableInstanceCache() {
|
||||
return this.cache;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||
import com.mojang.math.Axis;
|
||||
import com.vinlanx.explosionoverhaul.VinlanxTheLightItem;
|
||||
import com.vinlanx.explosionoverhaul.VinlanxTheLightModel;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemDisplayContext;
|
||||
import software.bernie.geckolib.cache.object.BakedGeoModel;
|
||||
import software.bernie.geckolib.renderer.GeoItemRenderer;
|
||||
|
||||
public class VinlanxTheLightItemRenderer
|
||||
extends GeoItemRenderer<VinlanxTheLightItem> {
|
||||
public VinlanxTheLightItemRenderer() {
|
||||
super(new VinlanxTheLightModel());
|
||||
}
|
||||
|
||||
public void preRender(PoseStack poseStack, VinlanxTheLightItem animatable, BakedGeoModel model, MultiBufferSource bufferSource, VertexConsumer buffer, boolean isReRender, float partialTick, int packedLight, int packedOverlay, float red, float green, float blue, float alpha) {
|
||||
super.preRender(poseStack, (Item)animatable, model, bufferSource, buffer, isReRender, partialTick, packedLight, packedOverlay, red, green, blue, alpha);
|
||||
if (this.renderPerspective == ItemDisplayContext.GUI || this.renderPerspective == ItemDisplayContext.FIXED) {
|
||||
poseStack.m_252781_(Axis.f_252436_.m_252977_(180.0f));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import software.bernie.geckolib.core.animatable.GeoAnimatable;
|
||||
import software.bernie.geckolib.model.GeoModel;
|
||||
|
||||
public class VinlanxTheLightModel<T extends GeoAnimatable>
|
||||
extends GeoModel<T> {
|
||||
private static final ResourceLocation MODEL = ResourceLocation.fromNamespaceAndPath((String)"explosionoverhaul", (String)"geo/vinlanxthelight.geo.json");
|
||||
private static final ResourceLocation TEXTURE = ResourceLocation.fromNamespaceAndPath((String)"explosionoverhaul", (String)"textures/block/vinlanxthelight.png");
|
||||
private static final ResourceLocation ANIMATION = ResourceLocation.fromNamespaceAndPath((String)"explosionoverhaul", (String)"animations/vinlanxthelight.animation.json");
|
||||
|
||||
public ResourceLocation getModelResource(T animatable) {
|
||||
return MODEL;
|
||||
}
|
||||
|
||||
public ResourceLocation getTextureResource(T animatable) {
|
||||
return TEXTURE;
|
||||
}
|
||||
|
||||
public ResourceLocation getAnimationResource(T animatable) {
|
||||
return ANIMATION;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul;
|
||||
|
||||
import com.vinlanx.explosionoverhaul.VinlanxTheLightBlockEntity;
|
||||
import com.vinlanx.explosionoverhaul.VinlanxTheLightModel;
|
||||
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider;
|
||||
import software.bernie.geckolib.renderer.GeoBlockRenderer;
|
||||
|
||||
public class VinlanxTheLightRenderer
|
||||
extends GeoBlockRenderer<VinlanxTheLightBlockEntity> {
|
||||
public VinlanxTheLightRenderer(BlockEntityRendererProvider.Context context) {
|
||||
super(new VinlanxTheLightModel());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul.api;
|
||||
|
||||
public interface IExplosionPower {
|
||||
public float getPower();
|
||||
|
||||
public void setPower(float var1);
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul.client;
|
||||
|
||||
import com.vinlanx.explosionoverhaul.ModSounds;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.resources.sounds.SimpleSoundInstance;
|
||||
import net.minecraft.client.resources.sounds.SoundInstance;
|
||||
import net.minecraft.sounds.SoundEvent;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.neoforged.neoforge.registries.RegistryObject;
|
||||
|
||||
public class AnimationSoundManager {
|
||||
private static final RandomSource RANDOM = RandomSource.m_216327_();
|
||||
private static final List<RegistryObject<SoundEvent>> ANIMATION_SOUNDS = new ArrayList<RegistryObject<SoundEvent>>();
|
||||
private static final List<RegistryObject<SoundEvent>> FAR_POWER_2_SOUNDS = new ArrayList<RegistryObject<SoundEvent>>();
|
||||
private static final List<RegistryObject<SoundEvent>> FAR_POWER_3_SOUNDS = new ArrayList<RegistryObject<SoundEvent>>();
|
||||
private static final List<RegistryObject<SoundEvent>> MEDIUM_CAVE_POWER_4_SOUNDS = new ArrayList<RegistryObject<SoundEvent>>();
|
||||
private static final List<RegistryObject<SoundEvent>> SUPERFAR_POWER_4_SOUNDS = new ArrayList<RegistryObject<SoundEvent>>();
|
||||
private static int lastAnimationSoundIndex = -1;
|
||||
private static int lastFarPower2SoundIndex = -1;
|
||||
private static int lastFarPower3SoundIndex = -1;
|
||||
private static int lastMediumCavePower4SoundIndex = -1;
|
||||
private static int lastSuperfar4SoundIndex = -1;
|
||||
|
||||
private static int getNextRandomIndex(List<?> list, int lastIndex) {
|
||||
int nextIndex;
|
||||
if (list.size() <= 1) {
|
||||
return 0;
|
||||
}
|
||||
while ((nextIndex = RANDOM.m_188503_(list.size())) == lastIndex) {
|
||||
}
|
||||
return nextIndex;
|
||||
}
|
||||
|
||||
public static void playRandomAnimationSound() {
|
||||
if (ANIMATION_SOUNDS.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
lastAnimationSoundIndex = AnimationSoundManager.getNextRandomIndex(ANIMATION_SOUNDS, lastAnimationSoundIndex);
|
||||
SoundEvent sound = (SoundEvent)ANIMATION_SOUNDS.get(lastAnimationSoundIndex).get();
|
||||
Minecraft.m_91087_().m_91106_().m_120367_((SoundInstance)SimpleSoundInstance.m_119752_((SoundEvent)sound, (float)1.0f));
|
||||
}
|
||||
|
||||
public static void playRandomFarPower2Sound() {
|
||||
if (FAR_POWER_2_SOUNDS.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
lastFarPower2SoundIndex = AnimationSoundManager.getNextRandomIndex(FAR_POWER_2_SOUNDS, lastFarPower2SoundIndex);
|
||||
SoundEvent sound = (SoundEvent)FAR_POWER_2_SOUNDS.get(lastFarPower2SoundIndex).get();
|
||||
Minecraft.m_91087_().m_91106_().m_120367_((SoundInstance)SimpleSoundInstance.m_119752_((SoundEvent)sound, (float)1.0f));
|
||||
}
|
||||
|
||||
public static void playRandomFarPower3Sound() {
|
||||
if (FAR_POWER_3_SOUNDS.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
lastFarPower3SoundIndex = AnimationSoundManager.getNextRandomIndex(FAR_POWER_3_SOUNDS, lastFarPower3SoundIndex);
|
||||
SoundEvent sound = (SoundEvent)FAR_POWER_3_SOUNDS.get(lastFarPower3SoundIndex).get();
|
||||
Minecraft.m_91087_().m_91106_().m_120367_((SoundInstance)SimpleSoundInstance.m_119752_((SoundEvent)sound, (float)1.0f));
|
||||
}
|
||||
|
||||
public static void playRandomMediumCavePower4Sound() {
|
||||
if (MEDIUM_CAVE_POWER_4_SOUNDS.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
lastMediumCavePower4SoundIndex = AnimationSoundManager.getNextRandomIndex(MEDIUM_CAVE_POWER_4_SOUNDS, lastMediumCavePower4SoundIndex);
|
||||
SoundEvent sound = (SoundEvent)MEDIUM_CAVE_POWER_4_SOUNDS.get(lastMediumCavePower4SoundIndex).get();
|
||||
Minecraft.m_91087_().m_91106_().m_120367_((SoundInstance)SimpleSoundInstance.m_119752_((SoundEvent)sound, (float)1.0f));
|
||||
}
|
||||
|
||||
public static void playRandomSuperfar4Sound() {
|
||||
if (SUPERFAR_POWER_4_SOUNDS.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
lastSuperfar4SoundIndex = AnimationSoundManager.getNextRandomIndex(SUPERFAR_POWER_4_SOUNDS, lastSuperfar4SoundIndex);
|
||||
SoundEvent sound = (SoundEvent)SUPERFAR_POWER_4_SOUNDS.get(lastSuperfar4SoundIndex).get();
|
||||
Minecraft.m_91087_().m_91106_().m_120367_((SoundInstance)SimpleSoundInstance.m_119752_((SoundEvent)sound, (float)1.0f));
|
||||
}
|
||||
|
||||
static {
|
||||
ANIMATION_SOUNDS.add(ModSounds.EXPLODE_SUPERFAR_POWER_2_1);
|
||||
ANIMATION_SOUNDS.add(ModSounds.EXPLODE_SUPERFAR_POWER_2_2);
|
||||
ANIMATION_SOUNDS.add(ModSounds.EXPLODE_SUPERFAR_POWER_3_1);
|
||||
FAR_POWER_2_SOUNDS.add(ModSounds.EXPLODE_FAR_POWER_2_1);
|
||||
FAR_POWER_2_SOUNDS.add(ModSounds.EXPLODE_FAR_POWER_2_2);
|
||||
FAR_POWER_2_SOUNDS.add(ModSounds.EXPLODE_FAR_POWER_2_3);
|
||||
FAR_POWER_3_SOUNDS.add(ModSounds.EXPLODE_FAR_POWER_3_1);
|
||||
FAR_POWER_3_SOUNDS.add(ModSounds.EXPLODE_FAR_POWER_3_2);
|
||||
FAR_POWER_3_SOUNDS.add(ModSounds.EXPLODE_FAR_POWER_3_3);
|
||||
MEDIUM_CAVE_POWER_4_SOUNDS.add(ModSounds.EXPLODE_MEDIUM_CAVE_POWER_4_1);
|
||||
MEDIUM_CAVE_POWER_4_SOUNDS.add(ModSounds.EXPLODE_MEDIUM_CAVE_POWER_4_2);
|
||||
MEDIUM_CAVE_POWER_4_SOUNDS.add(ModSounds.EXPLODE_MEDIUM_CAVE_POWER_4_3);
|
||||
SUPERFAR_POWER_4_SOUNDS.add(ModSounds.EXPLODE_SUPERFAR_POWER_4_1);
|
||||
SUPERFAR_POWER_4_SOUNDS.add(ModSounds.EXPLODE_SUPERFAR_POWER_4_2);
|
||||
SUPERFAR_POWER_4_SOUNDS.add(ModSounds.EXPLODE_SUPERFAR_POWER_4_3);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul.client;
|
||||
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.util.RandomSource;
|
||||
|
||||
public class BackgroundParticle {
|
||||
public float x;
|
||||
public float y;
|
||||
public float vx;
|
||||
public float vy;
|
||||
public float size;
|
||||
public float life;
|
||||
public float maxLife;
|
||||
public int color;
|
||||
public ParticleType type;
|
||||
|
||||
public BackgroundParticle(float x, float y, float vx, float vy, float size, float life, int color, ParticleType type) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.vx = vx;
|
||||
this.vy = vy;
|
||||
this.size = size;
|
||||
this.life = life;
|
||||
this.maxLife = life;
|
||||
this.color = color;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public void tick(float deltaTime) {
|
||||
this.x += this.vx * deltaTime * 60.0f;
|
||||
this.y += this.vy * deltaTime * 60.0f;
|
||||
this.life -= deltaTime;
|
||||
if (this.type == ParticleType.EMBER) {
|
||||
this.vy += 0.5f * deltaTime * 60.0f;
|
||||
}
|
||||
if (this.type == ParticleType.SMOKE) {
|
||||
this.size += 0.3f * deltaTime * 60.0f;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isDead() {
|
||||
return this.life <= 0.0f;
|
||||
}
|
||||
|
||||
public float getAlpha() {
|
||||
float lifeRatio = this.life / this.maxLife;
|
||||
if (this.type == ParticleType.FLASH) {
|
||||
return lifeRatio > 0.7f ? 1.0f - (lifeRatio - 0.7f) / 0.3f : lifeRatio / 0.7f;
|
||||
}
|
||||
return Mth.m_14036_((float)lifeRatio, (float)0.0f, (float)1.0f);
|
||||
}
|
||||
|
||||
public static BackgroundParticle createSpark(RandomSource random, int screenWidth, int screenHeight) {
|
||||
float x = random.m_188501_() * (float)screenWidth;
|
||||
float y = random.m_188501_() * (float)screenHeight;
|
||||
float angle = random.m_188501_() * (float)Math.PI * 2.0f;
|
||||
float speed = 2.0f + random.m_188501_() * 4.0f;
|
||||
float vx = (float)Math.cos(angle) * speed;
|
||||
float vy = (float)Math.sin(angle) * speed;
|
||||
float size = 1.0f + random.m_188501_() * 2.0f;
|
||||
float life = 0.5f + random.m_188501_() * 1.5f;
|
||||
int[] colors = new int[]{-881908, -21965, -8841, -86};
|
||||
int color = colors[random.m_188503_(colors.length)];
|
||||
return new BackgroundParticle(x, y, vx, vy, size, life, color, ParticleType.SPARK);
|
||||
}
|
||||
|
||||
public static BackgroundParticle createEmber(RandomSource random, int screenWidth, int screenHeight) {
|
||||
float x = random.m_188501_() * (float)screenWidth;
|
||||
float y = -20.0f;
|
||||
float vx = (random.m_188501_() - 0.5f) * 2.0f;
|
||||
float vy = 1.0f + random.m_188501_() * 2.0f;
|
||||
float size = 2.0f + random.m_188501_() * 4.0f;
|
||||
float life = 3.0f + random.m_188501_() * 4.0f;
|
||||
int[] colors = new int[]{-4250588, -2529701, -10939115, -48094};
|
||||
int color = colors[random.m_188503_(colors.length)];
|
||||
return new BackgroundParticle(x, y, vx, vy, size, life, color, ParticleType.EMBER);
|
||||
}
|
||||
|
||||
public static BackgroundParticle createFlash(RandomSource random, int screenWidth, int screenHeight) {
|
||||
float x = random.m_188501_() * (float)screenWidth;
|
||||
float y = random.m_188501_() * (float)screenHeight;
|
||||
float size = 30.0f + random.m_188501_() * 70.0f;
|
||||
float life = 0.2f + random.m_188501_() * 0.4f;
|
||||
int[] colors = new int[]{-881908, -4250588, -21948};
|
||||
int color = colors[random.m_188503_(colors.length)];
|
||||
return new BackgroundParticle(x, y, 0.0f, 0.0f, size, life, color, ParticleType.FLASH);
|
||||
}
|
||||
|
||||
public static BackgroundParticle createSmoke(RandomSource random, int screenWidth, int screenHeight) {
|
||||
float x = random.m_188501_() * (float)screenWidth;
|
||||
float y = (float)screenHeight + 20.0f;
|
||||
float vx = (random.m_188501_() - 0.5f) * 1.0f;
|
||||
float vy = -1.0f - random.m_188501_() * 2.0f;
|
||||
float size = 15.0f + random.m_188501_() * 30.0f;
|
||||
float life = 4.0f + random.m_188501_() * 6.0f;
|
||||
int gray = 13 + random.m_188503_(30);
|
||||
int color = 0xFF000000 | gray << 16 | gray << 8 | gray;
|
||||
return new BackgroundParticle(x, y, vx, vy, size, life, color, ParticleType.SMOKE);
|
||||
}
|
||||
|
||||
public static enum ParticleType {
|
||||
SPARK,
|
||||
EMBER,
|
||||
FLASH,
|
||||
SMOKE;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,495 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul.client;
|
||||
|
||||
import com.vinlanx.explosionoverhaul.BlockIndexManager;
|
||||
import com.vinlanx.explosionoverhaul.ExplosionOverhaul;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumMap;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiGraphics;
|
||||
import net.minecraft.client.gui.components.Button;
|
||||
import net.minecraft.client.gui.components.CycleButton;
|
||||
import net.minecraft.client.gui.components.EditBox;
|
||||
import net.minecraft.client.gui.components.ObjectSelectionList;
|
||||
import net.minecraft.client.gui.components.Tooltip;
|
||||
import net.minecraft.client.gui.components.events.GuiEventListener;
|
||||
import net.minecraft.client.gui.screens.Screen;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.FormattedText;
|
||||
import net.minecraft.network.chat.MutableComponent;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.Items;
|
||||
import net.minecraft.world.level.ItemLike;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.neoforged.neoforge.registries.ForgeRegistries;
|
||||
|
||||
public class BlacklistScreen
|
||||
extends Screen {
|
||||
private static final int NAV_WIDTH = 160;
|
||||
private static final int PADDING = 12;
|
||||
private static final int HEADER_HEIGHT = 48;
|
||||
private static final int FOOTER_HEIGHT = 64;
|
||||
private static final int SEARCH_WIDTH = 200;
|
||||
private static final int INPUT_WIDTH = 240;
|
||||
private static final int BUTTON_HEIGHT = 20;
|
||||
private static final int SPACING = 4;
|
||||
private final Screen parent;
|
||||
private BlacklistList widget;
|
||||
private EditBox inputField;
|
||||
private Button addButton;
|
||||
private EditBox searchField;
|
||||
private Button backButton;
|
||||
private Button resetButton;
|
||||
private Button infoButton;
|
||||
private CycleButton<Boolean> defaultToggle;
|
||||
private final LinkedHashSet<String> persistedEntries = new LinkedHashSet();
|
||||
private final Map<String, ExplosionOverhaul.ExplosionSourceMode> persistedSourceModes = new HashMap<String, ExplosionOverhaul.ExplosionSourceMode>();
|
||||
private final Set<String> defaultEntries = new LinkedHashSet<String>();
|
||||
private boolean showDefaults = false;
|
||||
private final EnumMap<BlacklistCategory, Button> categoryButtons = new EnumMap(BlacklistCategory.class);
|
||||
private BlacklistCategory currentCategory = BlacklistCategory.EXPLOSION;
|
||||
private List<String> suggestions = Collections.emptyList();
|
||||
private List<String> registryCache = new ArrayList<String>();
|
||||
|
||||
public BlacklistScreen(Screen parent) {
|
||||
super((Component)Component.m_237115_((String)"title.explosionoverhaul.blacklist"));
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
protected void m_7856_() {
|
||||
this.categoryButtons.clear();
|
||||
this.setupLayout();
|
||||
this.addNavigation();
|
||||
this.addTopControls();
|
||||
this.addInputArea();
|
||||
this.updateCache();
|
||||
this.loadCurrentCategoryEntries();
|
||||
}
|
||||
|
||||
private void setupLayout() {
|
||||
int listTop = 48;
|
||||
int listBottom = this.f_96544_ - 64;
|
||||
int listWidth = this.f_96543_ - 160 - 24;
|
||||
int listLeft = 172;
|
||||
this.widget = new BlacklistList(this.f_96541_, listWidth, listBottom - listTop, listTop, listBottom, 24);
|
||||
this.widget.m_93507_(listLeft);
|
||||
this.m_142416_((GuiEventListener)this.widget);
|
||||
}
|
||||
|
||||
private void addNavigation() {
|
||||
int buttonY = 48;
|
||||
for (BlacklistCategory category : BlacklistCategory.values()) {
|
||||
Button button = Button.m_253074_((Component)this.formatCategoryLabel(category), b -> this.selectCategory(category)).m_252794_(12, buttonY).m_253046_(160, 20).m_257505_(Tooltip.m_257550_((Component)Component.m_237115_((String)category.getTooltipKey()))).m_253136_();
|
||||
this.categoryButtons.put(category, button);
|
||||
this.m_142416_((GuiEventListener)button);
|
||||
buttonY += 24;
|
||||
}
|
||||
}
|
||||
|
||||
private void addTopControls() {
|
||||
int listLeft = 172;
|
||||
this.backButton = Button.m_253074_((Component)Component.m_237115_((String)"gui.back"), b -> this.m_7379_()).m_252794_(12, 12).m_253046_(80, 20).m_253136_();
|
||||
this.m_142416_((GuiEventListener)this.backButton);
|
||||
this.searchField = new EditBox(this.f_96547_, listLeft, 26, 200, 18, (Component)Component.m_237119_());
|
||||
this.searchField.m_257771_((Component)Component.m_237115_((String)"option.explosionoverhaul.blacklist_search"));
|
||||
this.searchField.m_94151_(s -> this.refreshList());
|
||||
this.m_142416_((GuiEventListener)this.searchField);
|
||||
this.resetButton = Button.m_253074_((Component)Component.m_237115_((String)"option.explosionoverhaul.reset_list"), this::onResetClicked).m_252794_(this.f_96543_ - 250, 12).m_253046_(60, 20).m_257505_(Tooltip.m_257550_((Component)Component.m_237115_((String)"tooltip.explosionoverhaul.reset_list"))).m_253136_();
|
||||
this.m_142416_((GuiEventListener)this.resetButton);
|
||||
this.defaultToggle = CycleButton.m_168916_((boolean)this.showDefaults).m_232498_(value -> Tooltip.m_257550_((Component)Component.m_237115_((String)"tooltip.explosionoverhaul.show_defaults"))).m_168936_(this.f_96543_ - 180, 12, 168, 20, (Component)Component.m_237115_((String)"option.explosionoverhaul.show_defaults"), (btn, value) -> {
|
||||
this.showDefaults = value;
|
||||
this.refreshList();
|
||||
});
|
||||
this.m_142416_((GuiEventListener)this.defaultToggle);
|
||||
}
|
||||
|
||||
private void addInputArea() {
|
||||
int y = this.f_96544_ - 28;
|
||||
this.inputField = new EditBox(this.f_96547_, (this.f_96543_ - 240) / 2, y, 240, 18, (Component)Component.m_237119_());
|
||||
this.inputField.m_94199_(128);
|
||||
this.inputField.m_257771_((Component)Component.m_237115_((String)"option.explosionoverhaul.blacklist_input"));
|
||||
this.inputField.m_94151_(this::updateSuggestions);
|
||||
this.m_142416_((GuiEventListener)this.inputField);
|
||||
this.addButton = Button.m_253074_((Component)Component.m_237115_((String)"option.explosionoverhaul.blacklist_add"), b -> this.addCurrentInput()).m_252794_(this.inputField.m_252754_() + 240 + 8, this.inputField.m_252907_() - 1).m_253046_(80, 20).m_253136_();
|
||||
this.m_142416_((GuiEventListener)this.addButton);
|
||||
this.infoButton = Button.m_253074_((Component)Component.m_237115_((String)"option.explosionoverhaul.blacklist_info"), b -> {}).m_252794_(this.addButton.m_252754_() + 80 + 4, this.addButton.m_252907_()).m_253046_(40, 20).m_257505_(Tooltip.m_257550_((Component)Component.m_237115_((String)"tooltip.explosionoverhaul.blacklist_info"))).m_253136_();
|
||||
this.infoButton.f_93624_ = this.currentCategory == BlacklistCategory.SOURCES;
|
||||
this.m_142416_((GuiEventListener)this.infoButton);
|
||||
}
|
||||
|
||||
private void onResetClicked(Button b) {
|
||||
if (BlacklistScreen.m_96638_()) {
|
||||
List<String> defaults = this.currentCategory.loadDefaults();
|
||||
this.currentCategory.saveEntries(defaults);
|
||||
this.persistedEntries.clear();
|
||||
this.persistedEntries.addAll(defaults);
|
||||
if (this.currentCategory == BlacklistCategory.SOURCES) {
|
||||
this.persistedSourceModes.clear();
|
||||
this.save();
|
||||
}
|
||||
this.refreshList();
|
||||
this.displayStatus((Component)Component.m_237115_((String)"message.explosionoverhaul.list_reset"));
|
||||
}
|
||||
}
|
||||
|
||||
private void updateCache() {
|
||||
LinkedHashSet<String> uniqueRegistry = new LinkedHashSet<String>();
|
||||
if (this.currentCategory == BlacklistCategory.SOURCES) {
|
||||
uniqueRegistry.add("generic");
|
||||
ForgeRegistries.ENTITY_TYPES.getKeys().stream().map(ResourceLocation::toString).forEach(uniqueRegistry::add);
|
||||
ForgeRegistries.BLOCKS.getKeys().stream().map(ResourceLocation::toString).forEach(uniqueRegistry::add);
|
||||
ForgeRegistries.ITEMS.getKeys().stream().map(ResourceLocation::toString).forEach(uniqueRegistry::add);
|
||||
} else {
|
||||
ForgeRegistries.BLOCKS.getKeys().stream().map(ResourceLocation::toString).forEach(uniqueRegistry::add);
|
||||
}
|
||||
this.registryCache = new ArrayList<String>(uniqueRegistry);
|
||||
}
|
||||
|
||||
private void loadCurrentCategoryEntries() {
|
||||
this.persistedEntries.clear();
|
||||
this.persistedEntries.addAll(this.currentCategory.loadEntries());
|
||||
if (this.currentCategory == BlacklistCategory.SOURCES) {
|
||||
this.persistedSourceModes.clear();
|
||||
this.persistedSourceModes.putAll(ExplosionOverhaul.getSourceModes());
|
||||
}
|
||||
this.defaultEntries.clear();
|
||||
this.defaultEntries.addAll(this.currentCategory.loadDefaults());
|
||||
this.refreshList();
|
||||
}
|
||||
|
||||
private void selectCategory(BlacklistCategory category) {
|
||||
if (this.currentCategory == category) {
|
||||
return;
|
||||
}
|
||||
this.currentCategory = category;
|
||||
this.updateCache();
|
||||
this.loadCurrentCategoryEntries();
|
||||
this.updateCategoryButtons();
|
||||
if (this.infoButton != null) {
|
||||
boolean bl = this.infoButton.f_93624_ = this.currentCategory == BlacklistCategory.SOURCES;
|
||||
}
|
||||
if (this.inputField != null) {
|
||||
this.inputField.m_94144_("");
|
||||
this.updateSuggestions("");
|
||||
this.inputField.m_257771_((Component)Component.m_237115_((String)(this.currentCategory == BlacklistCategory.SOURCES ? "option.explosionoverhaul.blacklist_input_entities" : "option.explosionoverhaul.blacklist_input")));
|
||||
}
|
||||
}
|
||||
|
||||
private void updateCategoryButtons() {
|
||||
this.categoryButtons.forEach((category, button) -> button.m_93666_(this.formatCategoryLabel((BlacklistCategory)((Object)category))));
|
||||
}
|
||||
|
||||
private Component formatCategoryLabel(BlacklistCategory category) {
|
||||
MutableComponent label = Component.m_237115_((String)category.getLabelKey());
|
||||
if (category == this.currentCategory) {
|
||||
return Component.m_237113_((String)"\u25b6 ").m_7220_((Component)label);
|
||||
}
|
||||
return label;
|
||||
}
|
||||
|
||||
private void refreshList() {
|
||||
String query = this.searchField == null ? "" : this.searchField.m_94155_().trim().toLowerCase(Locale.ROOT);
|
||||
boolean hasQuery = !query.isEmpty();
|
||||
ArrayList<BlacklistEntry> entries = new ArrayList<BlacklistEntry>();
|
||||
for (String id : this.persistedEntries) {
|
||||
boolean isDefault = this.defaultEntries.contains(id);
|
||||
if (!hasQuery && !this.showDefaults && isDefault || hasQuery && !id.toLowerCase(Locale.ROOT).contains(query)) continue;
|
||||
entries.add(new BlacklistEntry(id, isDefault));
|
||||
}
|
||||
this.widget.rebuild(entries);
|
||||
}
|
||||
|
||||
private void addCurrentInput() {
|
||||
String normalized;
|
||||
String raw = this.inputField.m_94155_().trim().toLowerCase(Locale.ROOT);
|
||||
if (raw.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (raw.equals("generic")) {
|
||||
normalized = "generic";
|
||||
} else {
|
||||
ResourceLocation id = ResourceLocation.m_135820_((String)(raw.contains(":") ? raw : "minecraft:" + raw));
|
||||
if (id == null) {
|
||||
this.displayStatus((Component)Component.m_237115_((String)"message.explosionoverhaul.invalid_id"));
|
||||
return;
|
||||
}
|
||||
normalized = id.toString();
|
||||
}
|
||||
if (!this.persistedEntries.add(normalized)) {
|
||||
this.displayStatus((Component)Component.m_237115_((String)"message.explosionoverhaul.duplicate_entry"));
|
||||
return;
|
||||
}
|
||||
if (this.currentCategory == BlacklistCategory.SOURCES) {
|
||||
this.persistedSourceModes.put(normalized, ExplosionOverhaul.ExplosionSourceMode.DEFAULT);
|
||||
}
|
||||
this.save();
|
||||
this.inputField.m_94144_("");
|
||||
this.updateSuggestions("");
|
||||
this.refreshList();
|
||||
}
|
||||
|
||||
private void removeEntry(String id) {
|
||||
if (this.persistedEntries.remove(id)) {
|
||||
if (this.currentCategory == BlacklistCategory.SOURCES) {
|
||||
this.persistedSourceModes.remove(id);
|
||||
}
|
||||
this.save();
|
||||
this.refreshList();
|
||||
}
|
||||
}
|
||||
|
||||
private void save() {
|
||||
if (this.currentCategory == BlacklistCategory.SOURCES) {
|
||||
HashMap<String, ExplosionOverhaul.ExplosionSourceMode> toSave = new HashMap<String, ExplosionOverhaul.ExplosionSourceMode>();
|
||||
for (String id : this.persistedEntries) {
|
||||
toSave.put(id, this.persistedSourceModes.getOrDefault(id, ExplosionOverhaul.ExplosionSourceMode.DEFAULT));
|
||||
}
|
||||
ExplosionOverhaul.setSourceModes(toSave);
|
||||
} else {
|
||||
this.currentCategory.saveEntries(new ArrayList<String>(this.persistedEntries));
|
||||
}
|
||||
}
|
||||
|
||||
private void updateSuggestions(String current) {
|
||||
String query = current.trim().toLowerCase(Locale.ROOT);
|
||||
if (query.isEmpty()) {
|
||||
this.suggestions = Collections.emptyList();
|
||||
return;
|
||||
}
|
||||
this.suggestions = this.registryCache.stream().filter(name -> name.startsWith(query)).limit(12L).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private void displayStatus(Component message) {
|
||||
if (this.f_96541_ != null && this.f_96541_.f_91065_ != null) {
|
||||
this.f_96541_.f_91065_.m_93063_(message, false);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean m_7933_(int keyCode, int scanCode, int modifiers) {
|
||||
if (this.inputField.m_93696_() && (keyCode == 257 || keyCode == 335)) {
|
||||
this.addCurrentInput();
|
||||
return true;
|
||||
}
|
||||
return super.m_7933_(keyCode, scanCode, modifiers);
|
||||
}
|
||||
|
||||
public void m_88315_(GuiGraphics graphics, int mouseX, int mouseY, float delta) {
|
||||
this.m_280273_(graphics);
|
||||
graphics.m_280614_(this.f_96547_, this.f_96539_, this.f_96543_ / 2 - this.f_96547_.m_92852_((FormattedText)this.f_96539_) / 2, 16, 0xFFFFFF, false);
|
||||
this.widget.m_88315_(graphics, mouseX, mouseY, delta);
|
||||
super.m_88315_(graphics, mouseX, mouseY, delta);
|
||||
this.inputField.m_88315_(graphics, mouseX, mouseY, delta);
|
||||
this.renderSuggestions(graphics, mouseX, mouseY);
|
||||
}
|
||||
|
||||
private void renderSuggestions(GuiGraphics graphics, int mouseX, int mouseY) {
|
||||
if (this.suggestions.isEmpty() || !this.inputField.m_93696_()) {
|
||||
return;
|
||||
}
|
||||
int x = this.inputField.m_252754_();
|
||||
int y = this.inputField.m_252907_() - this.suggestions.size() * 12 - 4;
|
||||
int width = this.inputField.m_5711_();
|
||||
int line = 0;
|
||||
for (String s : this.suggestions) {
|
||||
int yy = y + line * 12;
|
||||
graphics.m_280509_(x, yy, x + width, yy + 12, -1442840576);
|
||||
graphics.m_280056_(this.f_96547_, s, x + 4, yy + 2, 0xE0E0E0, false);
|
||||
++line;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean m_6375_(double mouseX, double mouseY, int button) {
|
||||
if (this.inputField.m_93696_() && !this.suggestions.isEmpty()) {
|
||||
int x = this.inputField.m_252754_();
|
||||
int y = this.inputField.m_252907_() - this.suggestions.size() * 12 - 4;
|
||||
int width = this.inputField.m_5711_();
|
||||
for (int i = 0; i < this.suggestions.size(); ++i) {
|
||||
int yy = y + i * 12;
|
||||
if (!(mouseX >= (double)x) || !(mouseX <= (double)(x + width)) || !(mouseY >= (double)yy) || !(mouseY <= (double)(yy + 12))) continue;
|
||||
this.inputField.m_94144_(this.suggestions.get(i));
|
||||
this.inputField.m_94196_(this.inputField.m_94155_().length());
|
||||
this.updateSuggestions(this.inputField.m_94155_());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return super.m_6375_(mouseX, mouseY, button);
|
||||
}
|
||||
|
||||
public void m_7379_() {
|
||||
this.save();
|
||||
this.f_96541_.m_91152_(this.parent);
|
||||
}
|
||||
|
||||
private static enum BlacklistCategory {
|
||||
EXPLOSION("option.explosionoverhaul.blacklist_category_explosion", "tooltip.explosionoverhaul.blacklist_category_explosion", ExplosionOverhaul::getExplosionBlacklistList, ExplosionOverhaul::getDefaultExplosionBlacklist, ExplosionOverhaul::setExplosionBlacklistFromList),
|
||||
GLASS("option.explosionoverhaul.blacklist_category_glass", "tooltip.explosionoverhaul.blacklist_category_glass", BlockIndexManager::getReinforcedGlassBlacklist, BlockIndexManager::getDefaultReinforcedGlassBlacklist, BlockIndexManager::setReinforcedGlassBlacklistFromList),
|
||||
SOURCES("option.explosionoverhaul.blacklist_category_sources", "tooltip.explosionoverhaul.blacklist_category_sources", () -> new ArrayList<String>(ExplosionOverhaul.getSourceModes().keySet()), ArrayList::new, list -> {});
|
||||
|
||||
private final String labelKey;
|
||||
private final String tooltipKey;
|
||||
private final Supplier<List<String>> entriesSupplier;
|
||||
private final Supplier<List<String>> defaultsSupplier;
|
||||
private final Consumer<List<String>> saveAction;
|
||||
|
||||
private BlacklistCategory(String labelKey, String tooltipKey, Supplier<List<String>> entriesSupplier, Supplier<List<String>> defaultsSupplier, Consumer<List<String>> saveAction) {
|
||||
this.labelKey = labelKey;
|
||||
this.tooltipKey = tooltipKey;
|
||||
this.entriesSupplier = entriesSupplier;
|
||||
this.defaultsSupplier = defaultsSupplier;
|
||||
this.saveAction = saveAction;
|
||||
}
|
||||
|
||||
String getLabelKey() {
|
||||
return this.labelKey;
|
||||
}
|
||||
|
||||
String getTooltipKey() {
|
||||
return this.tooltipKey;
|
||||
}
|
||||
|
||||
List<String> loadEntries() {
|
||||
return this.entriesSupplier.get();
|
||||
}
|
||||
|
||||
List<String> loadDefaults() {
|
||||
return this.defaultsSupplier.get();
|
||||
}
|
||||
|
||||
void saveEntries(List<String> entries) {
|
||||
this.saveAction.accept(entries);
|
||||
}
|
||||
}
|
||||
|
||||
private class BlacklistList
|
||||
extends ObjectSelectionList<BlacklistEntry> {
|
||||
public BlacklistList(Minecraft mc, int width, int height, int top, int bottom, int itemHeight) {
|
||||
super(mc, width, height, top, bottom, itemHeight);
|
||||
}
|
||||
|
||||
void rebuild(List<BlacklistEntry> entries) {
|
||||
this.m_5988_(entries);
|
||||
}
|
||||
|
||||
public int m_5759_() {
|
||||
return this.f_93388_ - 12;
|
||||
}
|
||||
|
||||
protected int m_5756_() {
|
||||
return this.m_5747_() + this.m_5759_();
|
||||
}
|
||||
|
||||
public boolean m_7979_(double mouseX, double mouseY, int button, double dragX, double dragY) {
|
||||
return super.m_7979_(mouseX, mouseY, button, dragX, dragY);
|
||||
}
|
||||
}
|
||||
|
||||
private class BlacklistEntry
|
||||
extends ObjectSelectionList.Entry<BlacklistEntry> {
|
||||
private final String id;
|
||||
private final boolean isDefault;
|
||||
private final Button removeButton;
|
||||
private CycleButton<ExplosionOverhaul.ExplosionSourceMode> modeButton;
|
||||
private ItemStack icon;
|
||||
private int lastX;
|
||||
private int lastY;
|
||||
private int lastRowWidth;
|
||||
private int lastRowHeight;
|
||||
|
||||
BlacklistEntry(String id, boolean isDefault) {
|
||||
this.id = id;
|
||||
this.isDefault = isDefault;
|
||||
if (BlacklistScreen.this.currentCategory == BlacklistCategory.SOURCES) {
|
||||
if (id.equals("generic")) {
|
||||
this.icon = new ItemStack((ItemLike)Items.f_41996_);
|
||||
} else {
|
||||
ResourceLocation rl = ResourceLocation.m_135820_((String)id);
|
||||
ItemStack stack = ItemStack.f_41583_;
|
||||
if (rl != null) {
|
||||
Block b2;
|
||||
stack = new ItemStack((ItemLike)ForgeRegistries.ITEMS.getValue(rl));
|
||||
if (stack.m_41619_()) {
|
||||
stack = new ItemStack((ItemLike)ForgeRegistries.ITEMS.getValue(new ResourceLocation(rl.m_135827_(), rl.m_135815_() + "_spawn_egg")));
|
||||
}
|
||||
if (stack.m_41619_() && (b2 = (Block)ForgeRegistries.BLOCKS.getValue(rl)) != Blocks.f_50016_) {
|
||||
stack = new ItemStack((ItemLike)b2.m_5456_());
|
||||
}
|
||||
}
|
||||
this.icon = stack.m_41619_() ? new ItemStack((ItemLike)Items.f_41996_) : stack;
|
||||
}
|
||||
ExplosionOverhaul.ExplosionSourceMode currentMode = BlacklistScreen.this.persistedSourceModes.getOrDefault(id, ExplosionOverhaul.ExplosionSourceMode.DEFAULT);
|
||||
String entryId = id;
|
||||
this.modeButton = CycleButton.m_168894_(m -> Component.m_237115_((String)("option.explosionoverhaul.sourcemode_" + m.name().toLowerCase(Locale.ROOT)))).m_168961_((Object[])ExplosionOverhaul.ExplosionSourceMode.values()).m_168948_((Object)currentMode).m_232498_(m -> Tooltip.m_257550_((Component)Component.m_237115_((String)("tooltip.explosionoverhaul.sourcemode_" + m.name().toLowerCase(Locale.ROOT))))).m_168936_(0, 0, 150, 20, (Component)Component.m_237119_(), (btn, value) -> {
|
||||
BlacklistScreen.this.persistedSourceModes.put(entryId, (ExplosionOverhaul.ExplosionSourceMode)((Object)value));
|
||||
BlacklistScreen.this.save();
|
||||
});
|
||||
} else {
|
||||
ItemStack stack;
|
||||
Block block = (Block)ForgeRegistries.BLOCKS.getValue(ResourceLocation.m_135820_((String)id));
|
||||
ItemStack itemStack = stack = block == null || block == Blocks.f_50016_ ? ItemStack.f_41583_ : new ItemStack((ItemLike)block.m_5456_());
|
||||
if (stack.m_41619_()) {
|
||||
stack = new ItemStack((ItemLike)Items.f_42127_);
|
||||
}
|
||||
this.icon = stack;
|
||||
}
|
||||
this.removeButton = Button.m_253074_((Component)Component.m_237113_((String)"\u2715"), b -> BlacklistScreen.this.removeEntry(this.id)).m_252794_(0, 0).m_253046_(20, 20).m_253136_();
|
||||
}
|
||||
|
||||
public Component m_142172_() {
|
||||
return Component.m_237113_((String)this.id);
|
||||
}
|
||||
|
||||
public boolean m_6375_(double mouseX, double mouseY, int button) {
|
||||
if (this.modeButton != null && this.modeButton.m_6375_(mouseX, mouseY, button)) {
|
||||
return true;
|
||||
}
|
||||
int btnX = this.lastX + this.lastRowWidth - 26;
|
||||
int btnY = this.lastY + (this.lastRowHeight - 20) / 2;
|
||||
if (mouseX >= (double)btnX && mouseX <= (double)(btnX + 20) && mouseY >= (double)btnY && mouseY <= (double)(btnY + 20)) {
|
||||
BlacklistScreen.this.removeEntry(this.id);
|
||||
return true;
|
||||
}
|
||||
return super.m_6375_(mouseX, mouseY, button);
|
||||
}
|
||||
|
||||
public void m_6311_(GuiGraphics graphics, int index, int y, int x, int rowWidth, int rowHeight, int mouseX, int mouseY, boolean hovered, float delta) {
|
||||
this.lastX = x;
|
||||
this.lastY = y;
|
||||
this.lastRowWidth = rowWidth;
|
||||
this.lastRowHeight = rowHeight;
|
||||
int iconX = x + 6;
|
||||
int iconY = y + (rowHeight - 16) / 2;
|
||||
try {
|
||||
graphics.m_280480_(this.icon, iconX, iconY);
|
||||
}
|
||||
catch (Throwable t) {
|
||||
this.icon = new ItemStack((ItemLike)Items.f_42127_);
|
||||
graphics.m_280480_(this.icon, iconX, iconY);
|
||||
}
|
||||
int textX = iconX + 22;
|
||||
int color = this.isDefault ? -5197648 : -1;
|
||||
graphics.m_280056_(BlacklistScreen.this.f_96547_, this.id, textX, y + (rowHeight - 8) / 2, color, false);
|
||||
if (this.modeButton != null) {
|
||||
int modeX = x + rowWidth - 180;
|
||||
this.modeButton.m_264152_(modeX, y + (rowHeight - 20) / 2);
|
||||
this.modeButton.m_88315_(graphics, mouseX, mouseY, delta);
|
||||
}
|
||||
int btnX = x + rowWidth - 26;
|
||||
this.removeButton.m_264152_(btnX, y + (rowHeight - 20) / 2);
|
||||
this.removeButton.m_88315_(graphics, mouseX, mouseY, delta);
|
||||
}
|
||||
}
|
||||
}
|
||||
262
src/main/java/com/vinlanx/explosionoverhaul/client/Blur.java
Normal file
262
src/main/java/com/vinlanx/explosionoverhaul/client/Blur.java
Normal file
@@ -0,0 +1,262 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul.client;
|
||||
|
||||
import com.mojang.blaze3d.pipeline.RenderTarget;
|
||||
import com.mojang.blaze3d.pipeline.TextureTarget;
|
||||
import com.mojang.blaze3d.shaders.Uniform;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.mojang.blaze3d.vertex.BufferBuilder;
|
||||
import com.mojang.blaze3d.vertex.BufferUploader;
|
||||
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
|
||||
import com.mojang.blaze3d.vertex.Tesselator;
|
||||
import com.mojang.blaze3d.vertex.VertexFormat;
|
||||
import com.vinlanx.explosionoverhaul.client.ConcussionAudioEffect;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.ShaderInstance;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.neoforged.api.distmarker.Dist;
|
||||
import net.neoforged.api.distmarker.OnlyIn;
|
||||
|
||||
@OnlyIn(value=Dist.CLIENT)
|
||||
public class Blur {
|
||||
private static final int FADE_IN_TICKS = 40;
|
||||
private static final int FADE_OUT_TICKS = 100;
|
||||
private static Phase phase = Phase.IDLE;
|
||||
private static int holdTicks = 0;
|
||||
private static int ticksInPhase = 0;
|
||||
private static ShaderInstance shader;
|
||||
private static RenderTarget blurTarget;
|
||||
private static int lastWidth;
|
||||
private static int lastHeight;
|
||||
private static float currentIntensity;
|
||||
private static float targetIntensity;
|
||||
private static float currentDesaturation;
|
||||
public static boolean APPLY_TO_HUD;
|
||||
public static boolean APPLY_TO_HAND;
|
||||
|
||||
public static boolean isActive() {
|
||||
return phase != Phase.IDLE;
|
||||
}
|
||||
|
||||
public static float getCurrentIntensity() {
|
||||
return currentIntensity;
|
||||
}
|
||||
|
||||
public static void setShader(ShaderInstance instance) {
|
||||
shader = instance;
|
||||
}
|
||||
|
||||
public static void setDesaturation(float v) {
|
||||
currentDesaturation = Mth.m_14036_((float)v, (float)0.0f, (float)1.0f);
|
||||
}
|
||||
|
||||
public static void start(int seconds) {
|
||||
Blur.start(seconds, 1.0f);
|
||||
}
|
||||
|
||||
public static void start(int seconds, float intensity) {
|
||||
int newHoldTicks = Mth.m_14045_((int)seconds, (int)1, (int)100) * 20;
|
||||
float newIntensity = Mth.m_14036_((float)intensity, (float)0.0f, (float)1.0f);
|
||||
if (phase != Phase.IDLE) {
|
||||
targetIntensity = Mth.m_14036_((float)(targetIntensity + newIntensity), (float)0.0f, (float)1.0f);
|
||||
holdTicks = Math.min(2000, holdTicks + newHoldTicks);
|
||||
if (phase == Phase.FADE_OUT) {
|
||||
phase = Phase.HOLD;
|
||||
ticksInPhase = 0;
|
||||
}
|
||||
} else {
|
||||
holdTicks = newHoldTicks;
|
||||
ticksInPhase = 0;
|
||||
targetIntensity = newIntensity;
|
||||
phase = Phase.FADE_IN;
|
||||
currentIntensity = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
public static void stop() {
|
||||
phase = Phase.IDLE;
|
||||
ticksInPhase = 0;
|
||||
holdTicks = 0;
|
||||
currentIntensity = 0.0f;
|
||||
targetIntensity = 0.0f;
|
||||
}
|
||||
|
||||
public static void onClientTick() {
|
||||
float intensity;
|
||||
Minecraft mc = Minecraft.m_91087_();
|
||||
if (mc.m_91104_() || phase == Phase.IDLE) {
|
||||
return;
|
||||
}
|
||||
++ticksInPhase;
|
||||
switch (phase) {
|
||||
case FADE_IN: {
|
||||
float t = Math.min(1.0f, (float)ticksInPhase / 40.0f);
|
||||
intensity = Blur.easeOutCubic(t) * targetIntensity;
|
||||
if (ticksInPhase < 40) break;
|
||||
phase = Phase.HOLD;
|
||||
ticksInPhase = 0;
|
||||
break;
|
||||
}
|
||||
case HOLD: {
|
||||
intensity = targetIntensity;
|
||||
if (ticksInPhase < holdTicks) break;
|
||||
phase = Phase.FADE_OUT;
|
||||
ticksInPhase = 0;
|
||||
break;
|
||||
}
|
||||
case FADE_OUT: {
|
||||
float t = Math.min(1.0f, (float)ticksInPhase / 100.0f);
|
||||
intensity = targetIntensity * (1.0f - Blur.easeInCubic(t));
|
||||
if (ticksInPhase < 100) break;
|
||||
currentIntensity = 0.0f;
|
||||
Blur.stop();
|
||||
return;
|
||||
}
|
||||
default: {
|
||||
intensity = 0.0f;
|
||||
}
|
||||
}
|
||||
currentIntensity = intensity;
|
||||
if (mc.f_91074_ != null) {
|
||||
ConcussionAudioEffect.updateHeartbeat(mc.f_91074_, currentIntensity);
|
||||
}
|
||||
}
|
||||
|
||||
public static void render(RenderStage stage) {
|
||||
if (phase == Phase.IDLE || shader == null) {
|
||||
return;
|
||||
}
|
||||
if (!Blur.shouldRenderStage(stage)) {
|
||||
return;
|
||||
}
|
||||
Minecraft mc = Minecraft.m_91087_();
|
||||
if (mc == null) {
|
||||
return;
|
||||
}
|
||||
RenderTarget mainTarget = mc.m_91385_();
|
||||
if (mainTarget == null) {
|
||||
return;
|
||||
}
|
||||
Blur.ensureTarget(mainTarget.f_83915_, mainTarget.f_83916_);
|
||||
if (blurTarget == null) {
|
||||
return;
|
||||
}
|
||||
RenderSystem.disableDepthTest();
|
||||
RenderSystem.depthMask((boolean)false);
|
||||
RenderSystem.disableBlend();
|
||||
RenderSystem.setShaderColor((float)1.0f, (float)1.0f, (float)1.0f, (float)1.0f);
|
||||
blurTarget.m_83947_(true);
|
||||
RenderSystem.viewport((int)0, (int)0, (int)Blur.blurTarget.f_83915_, (int)Blur.blurTarget.f_83916_);
|
||||
Blur.renderFullscreen(mainTarget.m_83975_(), currentIntensity, mainTarget.f_83915_, mainTarget.f_83916_);
|
||||
mainTarget.m_83947_(true);
|
||||
RenderSystem.viewport((int)0, (int)0, (int)mainTarget.f_83915_, (int)mainTarget.f_83916_);
|
||||
Blur.renderFullscreen(blurTarget.m_83975_(), 0.0f, mainTarget.f_83915_, mainTarget.f_83916_);
|
||||
RenderSystem.enableBlend();
|
||||
RenderSystem.defaultBlendFunc();
|
||||
RenderSystem.depthMask((boolean)true);
|
||||
RenderSystem.enableDepthTest();
|
||||
}
|
||||
|
||||
private static boolean shouldRenderStage(RenderStage stage) {
|
||||
if (APPLY_TO_HUD) {
|
||||
return stage == RenderStage.HUD;
|
||||
}
|
||||
if (APPLY_TO_HAND && Blur.isFirstPerson()) {
|
||||
return stage == RenderStage.HAND;
|
||||
}
|
||||
return stage == RenderStage.WORLD;
|
||||
}
|
||||
|
||||
private static boolean isFirstPerson() {
|
||||
Minecraft mc = Minecraft.m_91087_();
|
||||
if (mc == null) {
|
||||
return false;
|
||||
}
|
||||
return mc.f_91066_.m_92176_().m_90612_();
|
||||
}
|
||||
|
||||
private static void ensureTarget(int width, int height) {
|
||||
if (blurTarget == null || width != lastWidth || height != lastHeight) {
|
||||
if (blurTarget != null) {
|
||||
blurTarget.m_83930_();
|
||||
}
|
||||
blurTarget = new TextureTarget(width, height, false, Minecraft.f_91002_);
|
||||
lastWidth = width;
|
||||
lastHeight = height;
|
||||
}
|
||||
}
|
||||
|
||||
private static void renderFullscreen(int textureId, float intensity, int width, int height) {
|
||||
Uniform desatUniform;
|
||||
Uniform vignetteUniform;
|
||||
Uniform heartbeatUniform;
|
||||
Uniform outSizeUniform;
|
||||
Uniform inSizeUniform;
|
||||
RenderSystem.setShader(() -> shader);
|
||||
RenderSystem.setShaderTexture((int)0, (int)textureId);
|
||||
shader.m_173350_("DiffuseSampler", (Object)textureId);
|
||||
float clamped = Mth.m_14036_((float)intensity, (float)0.0f, (float)1.0f);
|
||||
Uniform intensityUniform = shader.m_173348_("Intensity");
|
||||
if (intensityUniform != null) {
|
||||
intensityUniform.m_5985_(clamped);
|
||||
}
|
||||
if ((inSizeUniform = shader.m_173348_("InSize")) != null) {
|
||||
inSizeUniform.m_7971_((float)width, (float)height);
|
||||
}
|
||||
if ((outSizeUniform = shader.m_173348_("OutSize")) != null) {
|
||||
outSizeUniform.m_7971_((float)width, (float)height);
|
||||
}
|
||||
if ((heartbeatUniform = shader.m_173348_("Heartbeat")) != null) {
|
||||
heartbeatUniform.m_5985_(ConcussionAudioEffect.getCurrentHeartbeatVisual());
|
||||
}
|
||||
if ((vignetteUniform = shader.m_173348_("Vignette")) != null) {
|
||||
vignetteUniform.m_5985_(1.0E-5f);
|
||||
}
|
||||
if ((desatUniform = shader.m_173348_("Desaturation")) != null) {
|
||||
desatUniform.m_5985_(clamped);
|
||||
}
|
||||
BufferBuilder builder = Tesselator.m_85913_().m_85915_();
|
||||
builder.m_166779_(VertexFormat.Mode.QUADS, DefaultVertexFormat.f_85817_);
|
||||
builder.m_5483_(-1.0, -1.0, 0.0).m_7421_(0.0f, 1.0f).m_5752_();
|
||||
builder.m_5483_(1.0, -1.0, 0.0).m_7421_(1.0f, 1.0f).m_5752_();
|
||||
builder.m_5483_(1.0, 1.0, 0.0).m_7421_(1.0f, 0.0f).m_5752_();
|
||||
builder.m_5483_(-1.0, 1.0, 0.0).m_7421_(0.0f, 0.0f).m_5752_();
|
||||
BufferUploader.m_231202_((BufferBuilder.RenderedBuffer)builder.m_231175_());
|
||||
}
|
||||
|
||||
private static float easeOutCubic(float t) {
|
||||
float inv = 1.0f - t;
|
||||
return 1.0f - inv * inv * inv;
|
||||
}
|
||||
|
||||
private static float easeInCubic(float t) {
|
||||
return t * t * t;
|
||||
}
|
||||
|
||||
static {
|
||||
lastWidth = -1;
|
||||
lastHeight = -1;
|
||||
currentIntensity = 0.0f;
|
||||
targetIntensity = 1.0f;
|
||||
currentDesaturation = 0.0f;
|
||||
APPLY_TO_HUD = false;
|
||||
APPLY_TO_HAND = true;
|
||||
}
|
||||
|
||||
private static enum Phase {
|
||||
IDLE,
|
||||
FADE_IN,
|
||||
HOLD,
|
||||
FADE_OUT;
|
||||
|
||||
}
|
||||
|
||||
public static enum RenderStage {
|
||||
WORLD,
|
||||
HAND,
|
||||
HUD;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul.client;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.player.LocalPlayer;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.neoforged.api.distmarker.Dist;
|
||||
import net.neoforged.api.distmarker.OnlyIn;
|
||||
|
||||
@OnlyIn(value=Dist.CLIENT)
|
||||
public class CameraShakeConcussionEffect {
|
||||
private static final int FADE_IN_TICKS = 40;
|
||||
private static final int FADE_OUT_TICKS = 40;
|
||||
private static Phase phase = Phase.IDLE;
|
||||
private static int ticksInPhase = 0;
|
||||
private static int holdTicks = 0;
|
||||
private static float currentIntensity = 0.0f;
|
||||
private static float targetIntensity = 0.0f;
|
||||
private static float lastYawOffset = 0.0f;
|
||||
private static float lastPitchOffset = 0.0f;
|
||||
|
||||
public static boolean isActive() {
|
||||
return phase != Phase.IDLE;
|
||||
}
|
||||
|
||||
public static void start(int seconds, float intensity) {
|
||||
int newHoldTicks = Mth.m_14045_((int)seconds, (int)1, (int)100) * 20;
|
||||
float newIntensity = Math.max(0.0f, intensity);
|
||||
if (phase != Phase.IDLE) {
|
||||
targetIntensity += newIntensity;
|
||||
holdTicks = Math.min(2000, holdTicks + newHoldTicks);
|
||||
if (phase == Phase.FADE_OUT) {
|
||||
phase = Phase.HOLD;
|
||||
ticksInPhase = 0;
|
||||
}
|
||||
} else {
|
||||
targetIntensity = newIntensity;
|
||||
holdTicks = newHoldTicks;
|
||||
ticksInPhase = 0;
|
||||
phase = Phase.FADE_IN;
|
||||
currentIntensity = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
public static void onClientTick() {
|
||||
Minecraft mc = Minecraft.m_91087_();
|
||||
if (mc.m_91104_()) {
|
||||
return;
|
||||
}
|
||||
LocalPlayer player = mc.f_91074_;
|
||||
if (player == null) {
|
||||
CameraShakeConcussionEffect.stop();
|
||||
return;
|
||||
}
|
||||
player.m_19884_((double)(-lastYawOffset), (double)(-lastPitchOffset));
|
||||
lastYawOffset = 0.0f;
|
||||
lastPitchOffset = 0.0f;
|
||||
if (phase == Phase.IDLE) {
|
||||
return;
|
||||
}
|
||||
++ticksInPhase;
|
||||
switch (phase) {
|
||||
case FADE_IN: {
|
||||
float t = (float)ticksInPhase / 40.0f;
|
||||
currentIntensity = CameraShakeConcussionEffect.easeInOutCubic(t) * targetIntensity;
|
||||
if (ticksInPhase < 40) break;
|
||||
phase = Phase.HOLD;
|
||||
ticksInPhase = 0;
|
||||
break;
|
||||
}
|
||||
case HOLD: {
|
||||
currentIntensity = targetIntensity;
|
||||
if (ticksInPhase < holdTicks) break;
|
||||
phase = Phase.FADE_OUT;
|
||||
ticksInPhase = 0;
|
||||
break;
|
||||
}
|
||||
case FADE_OUT: {
|
||||
float t = (float)ticksInPhase / 40.0f;
|
||||
currentIntensity = targetIntensity * CameraShakeConcussionEffect.easeInOutCubic(1.0f - t);
|
||||
if (ticksInPhase < 40) break;
|
||||
CameraShakeConcussionEffect.stop();
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (currentIntensity > 0.0f) {
|
||||
CameraShakeConcussionEffect.applySway(player, (float)player.f_19797_ + mc.m_91296_());
|
||||
}
|
||||
}
|
||||
|
||||
private static void applySway(LocalPlayer player, float totalTicks) {
|
||||
float horizontalSway = Mth.m_14031_((float)(totalTicks * 0.04f)) * 1.5f + Mth.m_14031_((float)(totalTicks * 0.025f)) * 1.0f;
|
||||
float verticalSway = Mth.m_14089_((float)(totalTicks * 0.035f)) * 0.8f + Mth.m_14031_((float)(totalTicks * 0.015f)) * 0.5f;
|
||||
float yawChange = horizontalSway * currentIntensity * 50.0f;
|
||||
float pitchChange = verticalSway * currentIntensity * 30.0f;
|
||||
player.m_19884_((double)yawChange, (double)pitchChange);
|
||||
lastYawOffset = yawChange;
|
||||
lastPitchOffset = pitchChange;
|
||||
}
|
||||
|
||||
public static void stop() {
|
||||
phase = Phase.IDLE;
|
||||
ticksInPhase = 0;
|
||||
holdTicks = 0;
|
||||
currentIntensity = 0.0f;
|
||||
targetIntensity = 0.0f;
|
||||
lastYawOffset = 0.0f;
|
||||
lastPitchOffset = 0.0f;
|
||||
}
|
||||
|
||||
private static float easeInOutCubic(float t) {
|
||||
return t < 0.5f ? 4.0f * t * t * t : 1.0f - (float)Math.pow(-2.0f * t + 2.0f, 3.0) / 2.0f;
|
||||
}
|
||||
|
||||
private static enum Phase {
|
||||
IDLE,
|
||||
FADE_IN,
|
||||
HOLD,
|
||||
FADE_OUT;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,481 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul.client;
|
||||
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.vinlanx.explosionoverhaul.Config;
|
||||
import com.vinlanx.explosionoverhaul.ModParticles;
|
||||
import com.vinlanx.explosionoverhaul.PlayTrackedSoundPacket;
|
||||
import com.vinlanx.explosionoverhaul.client.Blur;
|
||||
import com.vinlanx.explosionoverhaul.client.CameraShakeConcussionEffect;
|
||||
import com.vinlanx.explosionoverhaul.client.ExplosionWindController;
|
||||
import com.vinlanx.explosionoverhaul.client.GroundDustEffect;
|
||||
import com.vinlanx.explosionoverhaul.client.GroundMistEffect;
|
||||
import com.vinlanx.explosionoverhaul.client.PhysicsBasedExplosionEffect;
|
||||
import com.vinlanx.explosionoverhaul.client.PositionalSoundInstance;
|
||||
import com.vinlanx.explosionoverhaul.client.ShockwaveEffect;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiGraphics;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.client.player.LocalPlayer;
|
||||
import net.minecraft.client.resources.sounds.SoundInstance;
|
||||
import net.minecraft.client.sounds.SoundManager;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.particles.BlockParticleOption;
|
||||
import net.minecraft.core.particles.ParticleOptions;
|
||||
import net.minecraft.core.particles.ParticleTypes;
|
||||
import net.minecraft.core.particles.SimpleParticleType;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.sounds.SoundEvent;
|
||||
import net.minecraft.sounds.SoundSource;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.level.ClipContext;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraft.world.phys.HitResult;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.neoforged.neoforge.client.event.RenderGuiOverlayEvent;
|
||||
import net.neoforged.neoforge.registries.ForgeRegistries;
|
||||
|
||||
public class ClientEffects {
|
||||
private static float currentShakeIntensity = 0.0f;
|
||||
private static int shakeDurationTicks = 0;
|
||||
private static float currentPushIntensity = 0.0f;
|
||||
private static float lastYawOffset = 0.0f;
|
||||
private static float lastPitchOffset = 0.0f;
|
||||
private static final Random random = new Random();
|
||||
private static final List<PhysicsBasedExplosionEffect> activeExplosions = new ArrayList<PhysicsBasedExplosionEffect>();
|
||||
private static final List<TrackedSound> activeTrackedSounds = new ArrayList<TrackedSound>();
|
||||
private static final List<ShockwaveEffect> activeShockwaves = new ArrayList<ShockwaveEffect>();
|
||||
private static final List<GroundDustEffect> activeDustClouds = new ArrayList<GroundDustEffect>();
|
||||
private static final List<GroundMistEffect> activeMistClouds = new ArrayList<GroundMistEffect>();
|
||||
private static final List<FlashEffect> activeFlashEffects = new ArrayList<FlashEffect>();
|
||||
private static final List<PendingShake> pendingShakes = new ArrayList<PendingShake>();
|
||||
|
||||
public static void addTrackedSound(PlayTrackedSoundPacket msg) {
|
||||
SoundEvent sound = (SoundEvent)ForgeRegistries.SOUND_EVENTS.getValue(msg.getSoundId());
|
||||
if (sound != null) {
|
||||
activeTrackedSounds.add(new TrackedSound(msg.getExplosionPos(), sound, msg.getVolume(), msg.getPitch(), msg.getDelayTicks(), msg.isPlayerInHouse()));
|
||||
}
|
||||
}
|
||||
|
||||
private static Vec3 calculateSoundPosition(Player player, Vec3 explosionPos, boolean isPlayerInHouse) {
|
||||
float FIXED_DISTANCE = 45.0f;
|
||||
Vec3 playerPos = player.m_146892_();
|
||||
Vec3 startPos = isPlayerInHouse ? explosionPos : playerPos;
|
||||
Vec3 endPos = isPlayerInHouse ? playerPos : explosionPos;
|
||||
ClipContext context = new ClipContext(startPos, endPos, ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, (Entity)player);
|
||||
BlockHitResult hitResult = player.m_9236_().m_45547_(context);
|
||||
if (hitResult.m_6662_() == HitResult.Type.MISS) {
|
||||
Vec3 direction = explosionPos.m_82546_(playerPos).m_82541_();
|
||||
if (direction.m_82556_() < 0.001) {
|
||||
direction = player.m_20154_();
|
||||
}
|
||||
return playerPos.m_82549_(direction.m_82490_(45.0));
|
||||
}
|
||||
Vec3 hitPos = hitResult.m_82450_();
|
||||
Vec3 rayDir = endPos.m_82546_(startPos).m_82541_();
|
||||
return hitPos.m_82546_(rayDir.m_82490_(0.1));
|
||||
}
|
||||
|
||||
private static void handleTrackedSoundsTick() {
|
||||
Minecraft mc = Minecraft.m_91087_();
|
||||
if (mc.f_91074_ == null || mc.m_91106_() == null) {
|
||||
return;
|
||||
}
|
||||
Iterator<TrackedSound> iterator = activeTrackedSounds.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
TrackedSound tracked = iterator.next();
|
||||
if (tracked.isFinished()) {
|
||||
iterator.remove();
|
||||
continue;
|
||||
}
|
||||
tracked.tick((Player)mc.f_91074_, mc.m_91106_(), mc.f_91074_.m_217043_());
|
||||
}
|
||||
}
|
||||
|
||||
public static void triggerLocalCameraShake(float intensity, int durationTicks, float pushIntensity) {
|
||||
if (!((Boolean)Config.CLIENT.enableCameraShake.get()).booleanValue()) {
|
||||
return;
|
||||
}
|
||||
float amplifiedIntensity = intensity * (((Double)Config.CLIENT.cameraShakeAmplifier.get()).floatValue() * 10.0f);
|
||||
float amplifiedPush = 0.0f;
|
||||
if (((Boolean)Config.COMMON.enablePlayerShake.get()).booleanValue()) {
|
||||
amplifiedPush = pushIntensity * (((Double)Config.COMMON.playerShakeAmplifier.get()).floatValue() * 5.0f);
|
||||
}
|
||||
if (amplifiedIntensity > currentShakeIntensity || shakeDurationTicks == 0 || durationTicks > shakeDurationTicks) {
|
||||
currentShakeIntensity = amplifiedIntensity;
|
||||
shakeDurationTicks = durationTicks;
|
||||
currentPushIntensity = amplifiedPush;
|
||||
}
|
||||
}
|
||||
|
||||
public static void triggerDelayedCameraShake(float intensity, int durationTicks, float pushIntensity, int delayTicks) {
|
||||
if (!((Boolean)Config.CLIENT.enableCameraShake.get()).booleanValue()) {
|
||||
return;
|
||||
}
|
||||
if (delayTicks <= 0) {
|
||||
ClientEffects.triggerLocalCameraShake(intensity, durationTicks, pushIntensity);
|
||||
return;
|
||||
}
|
||||
pendingShakes.add(new PendingShake(delayTicks, intensity, durationTicks, pushIntensity));
|
||||
}
|
||||
|
||||
public static void triggerRealisticExplosion(Vec3 position, float power) {
|
||||
activeExplosions.add(new PhysicsBasedExplosionEffect(position, power));
|
||||
}
|
||||
|
||||
public static void addFlashEffect(Vec3 explosionPos, float power) {
|
||||
activeFlashEffects.add(new FlashEffect(explosionPos, power));
|
||||
}
|
||||
|
||||
public static void onClientTick() {
|
||||
if (Minecraft.m_91087_().m_91104_()) {
|
||||
return;
|
||||
}
|
||||
Blur.onClientTick();
|
||||
CameraShakeConcussionEffect.onClientTick();
|
||||
ExplosionWindController.tick();
|
||||
ClientEffects.handleCameraShakeTick();
|
||||
ClientEffects.handlePendingShakesTick();
|
||||
ClientEffects.handleTrackedSoundsTick();
|
||||
activeExplosions.removeIf(effect -> {
|
||||
effect.tick();
|
||||
return effect.isFinished();
|
||||
});
|
||||
activeShockwaves.removeIf(effect -> {
|
||||
effect.tick();
|
||||
return effect.isFinished();
|
||||
});
|
||||
activeDustClouds.removeIf(effect -> {
|
||||
effect.tick();
|
||||
return effect.isFinished();
|
||||
});
|
||||
activeMistClouds.removeIf(effect -> {
|
||||
effect.tick();
|
||||
return effect.isFinished();
|
||||
});
|
||||
activeFlashEffects.removeIf(effect -> effect.isFinished());
|
||||
}
|
||||
|
||||
public static void renderFlash(RenderGuiOverlayEvent.Post event) {
|
||||
if (!((Boolean)Config.CLIENT.enableFlashEffect.get()).booleanValue()) {
|
||||
return;
|
||||
}
|
||||
Minecraft mc = Minecraft.m_91087_();
|
||||
if (mc.f_91074_ == null || activeFlashEffects.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
float maxOpacity = 0.0f;
|
||||
for (FlashEffect effect : activeFlashEffects) {
|
||||
float opacity = effect.getCurrentOpacity((Player)mc.f_91074_);
|
||||
if (!(opacity > maxOpacity)) continue;
|
||||
maxOpacity = opacity;
|
||||
}
|
||||
if (maxOpacity <= 0.0f) {
|
||||
return;
|
||||
}
|
||||
GuiGraphics guiGraphics = event.getGuiGraphics();
|
||||
int screenWidth = mc.m_91268_().m_85445_();
|
||||
int screenHeight = mc.m_91268_().m_85446_();
|
||||
ResourceLocation flashTexture = ResourceLocation.fromNamespaceAndPath((String)"explosionoverhaul", (String)"textures/effects/flash.png");
|
||||
RenderSystem.enableBlend();
|
||||
RenderSystem.defaultBlendFunc();
|
||||
RenderSystem.setShaderColor((float)1.0f, (float)1.0f, (float)1.0f, (float)maxOpacity);
|
||||
guiGraphics.m_280163_(flashTexture, 0, 0, 0.0f, 0.0f, screenWidth, screenHeight, screenWidth, screenHeight);
|
||||
RenderSystem.disableBlend();
|
||||
RenderSystem.setShaderColor((float)1.0f, (float)1.0f, (float)1.0f, (float)1.0f);
|
||||
}
|
||||
|
||||
private static void handlePendingShakesTick() {
|
||||
if (pendingShakes.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
Iterator<PendingShake> it = pendingShakes.iterator();
|
||||
while (it.hasNext()) {
|
||||
PendingShake ps = it.next();
|
||||
--ps.delayTicks;
|
||||
if (ps.delayTicks > 0) continue;
|
||||
ClientEffects.triggerLocalCameraShake(ps.intensity, ps.durationTicks, ps.pushIntensity);
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
|
||||
public static void triggerShockwave(Vec3 position, float power) {
|
||||
activeShockwaves.add(new ShockwaveEffect(position, power));
|
||||
}
|
||||
|
||||
public static void triggerDustCloud(Vec3 position, float power) {
|
||||
if (!((Boolean)Config.CLIENT.enableGroundDustEffect.get()).booleanValue()) {
|
||||
return;
|
||||
}
|
||||
activeDustClouds.add(new GroundDustEffect(position, power));
|
||||
}
|
||||
|
||||
public static void triggerMistCloud(Vec3 position, float power) {
|
||||
if (!((Boolean)Config.CLIENT.enableGroundMistEffect.get()).booleanValue()) {
|
||||
return;
|
||||
}
|
||||
activeMistClouds.add(new GroundMistEffect(position, power));
|
||||
}
|
||||
|
||||
public static void triggerAmbientCaveDust(float power) {
|
||||
int i;
|
||||
Minecraft mc = Minecraft.m_91087_();
|
||||
LocalPlayer player = mc.f_91074_;
|
||||
ClientLevel level = mc.f_91073_;
|
||||
if (player == null || level == null) {
|
||||
return;
|
||||
}
|
||||
int particleCount = 15 + (int)((double)(power / 10.0f) * 3.5);
|
||||
particleCount = Mth.m_14045_((int)particleCount, (int)10, (int)70);
|
||||
BlockPos playerPos = player.m_20183_();
|
||||
BlockState ceilingState = Blocks.f_50069_.m_49966_();
|
||||
for (i = 3; i < 10; ++i) {
|
||||
BlockState state = level.m_8055_(playerPos.m_6630_(i));
|
||||
if (state.m_60795_()) continue;
|
||||
ceilingState = state;
|
||||
break;
|
||||
}
|
||||
for (i = 0; i < particleCount; ++i) {
|
||||
double x = player.m_20185_() + (random.nextDouble() - 0.5) * 16.0;
|
||||
double z = player.m_20189_() + (random.nextDouble() - 0.5) * 16.0;
|
||||
double y = player.m_20186_() + 4.0 + random.nextDouble() * 6.0;
|
||||
level.m_7106_((ParticleOptions)new BlockParticleOption(ParticleTypes.f_123814_, ceilingState), x, y, z, 0.0, -0.15, 0.0);
|
||||
}
|
||||
}
|
||||
|
||||
private static void handleCameraShakeTick() {
|
||||
Minecraft mc = Minecraft.m_91087_();
|
||||
LocalPlayer player = mc.f_91074_;
|
||||
if (player == null) {
|
||||
if (shakeDurationTicks > 0 || lastYawOffset != 0.0f || lastPitchOffset != 0.0f) {
|
||||
lastYawOffset = 0.0f;
|
||||
lastPitchOffset = 0.0f;
|
||||
shakeDurationTicks = 0;
|
||||
currentShakeIntensity = 0.0f;
|
||||
currentPushIntensity = 0.0f;
|
||||
}
|
||||
return;
|
||||
}
|
||||
player.m_19884_((double)(-lastYawOffset), (double)(-lastPitchOffset));
|
||||
lastYawOffset = 0.0f;
|
||||
lastPitchOffset = 0.0f;
|
||||
if (shakeDurationTicks > 0) {
|
||||
float progress = (float)shakeDurationTicks / 30.0f;
|
||||
float cameraIntensity = currentShakeIntensity * Mth.m_14031_((float)(progress * (float)Math.PI));
|
||||
float yawChange = (random.nextFloat() - 0.5f) * 2.0f * cameraIntensity;
|
||||
float pitchChange = (random.nextFloat() - 0.5f) * 1.0f * cameraIntensity;
|
||||
player.m_19884_((double)yawChange, (double)pitchChange);
|
||||
lastYawOffset = yawChange;
|
||||
lastPitchOffset = pitchChange;
|
||||
if (currentPushIntensity > 0.0f) {
|
||||
float pushFactor = currentPushIntensity * Mth.m_14031_((float)(progress * (float)Math.PI)) * 0.1f;
|
||||
player.m_5997_((random.nextDouble() - 0.5) * (double)pushFactor, 0.0, (random.nextDouble() - 0.5) * (double)pushFactor);
|
||||
}
|
||||
--shakeDurationTicks;
|
||||
} else {
|
||||
currentShakeIntensity = 0.0f;
|
||||
currentPushIntensity = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
public static void triggerLineSparks(Vec3 position, float power) {
|
||||
if (!((Boolean)Config.CLIENT.enableLineSparks.get()).booleanValue()) {
|
||||
return;
|
||||
}
|
||||
Minecraft mc = Minecraft.m_91087_();
|
||||
ClientLevel level = mc.f_91073_;
|
||||
if (level == null) {
|
||||
return;
|
||||
}
|
||||
double amountMultiplier = (Double)Config.CLIENT.lineSparkAmountMultiplier.get();
|
||||
if (amountMultiplier <= 0.0) {
|
||||
return;
|
||||
}
|
||||
int sparkCount = (int)((double)(power * 15.0f) * amountMultiplier);
|
||||
sparkCount = Mth.m_14045_((int)sparkCount, (int)15, (int)500);
|
||||
for (int i = 0; i < sparkCount; ++i) {
|
||||
Vec3 motion = new Vec3(random.nextDouble() - 0.5, random.nextDouble() - 0.5, random.nextDouble() - 0.5).m_82541_();
|
||||
float powerFraction = power / 100.0f;
|
||||
float force = random.nextFloat() < 0.25f ? Mth.m_14179_((float)powerFraction, (float)0.5f, (float)8.0f) * (0.9f + random.nextFloat() * 0.4f) : Mth.m_14179_((float)powerFraction, (float)0.3f, (float)4.5f) * (0.7f + random.nextFloat() * 0.4f);
|
||||
motion = motion.m_82490_((double)force);
|
||||
level.m_7106_((ParticleOptions)((SimpleParticleType)ModParticles.LINE_SPARK.get()), position.f_82479_, position.f_82480_, position.f_82481_, motion.f_82479_, motion.f_82480_, motion.f_82481_);
|
||||
}
|
||||
}
|
||||
|
||||
private static class TrackedSound {
|
||||
final Vec3 explosionPos;
|
||||
final SoundEvent sound;
|
||||
final float volume;
|
||||
final float pitch;
|
||||
long delayTicks;
|
||||
PositionalSoundInstance soundInstance;
|
||||
boolean started = false;
|
||||
private int updateCooldown = 0;
|
||||
private final boolean isPlayerInHouse;
|
||||
|
||||
TrackedSound(Vec3 explosionPos, SoundEvent sound, float volume, float pitch, long delayTicks, boolean isPlayerInHouse) {
|
||||
this.explosionPos = explosionPos;
|
||||
this.sound = sound;
|
||||
this.volume = volume;
|
||||
this.pitch = pitch;
|
||||
this.delayTicks = delayTicks;
|
||||
this.isPlayerInHouse = isPlayerInHouse;
|
||||
}
|
||||
|
||||
public void tick(Player player, SoundManager soundManager, RandomSource random) {
|
||||
if (this.soundInstance != null && this.soundInstance.m_7801_()) {
|
||||
return;
|
||||
}
|
||||
if (!this.started) {
|
||||
--this.delayTicks;
|
||||
if (this.delayTicks <= 0L) {
|
||||
Vec3 soundPos = ClientEffects.calculateSoundPosition(player, this.explosionPos, this.isPlayerInHouse);
|
||||
this.soundInstance = new PositionalSoundInstance(this.sound, SoundSource.BLOCKS, this.volume, this.pitch, random, soundPos.f_82479_, soundPos.f_82480_, soundPos.f_82481_);
|
||||
soundManager.m_120367_((SoundInstance)this.soundInstance);
|
||||
this.started = true;
|
||||
}
|
||||
} else {
|
||||
--this.updateCooldown;
|
||||
if (this.updateCooldown <= 0) {
|
||||
this.updateCooldown = 10;
|
||||
Vec3 newSoundPos = ClientEffects.calculateSoundPosition(player, this.explosionPos, this.isPlayerInHouse);
|
||||
this.soundInstance.updatePosition(newSoundPos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isFinished() {
|
||||
return this.soundInstance != null && this.soundInstance.m_7801_();
|
||||
}
|
||||
}
|
||||
|
||||
private static class PendingShake {
|
||||
int delayTicks;
|
||||
final float intensity;
|
||||
final int durationTicks;
|
||||
final float pushIntensity;
|
||||
|
||||
PendingShake(int delayTicks, float intensity, int durationTicks, float pushIntensity) {
|
||||
this.delayTicks = delayTicks;
|
||||
this.intensity = intensity;
|
||||
this.durationTicks = durationTicks;
|
||||
this.pushIntensity = pushIntensity;
|
||||
}
|
||||
}
|
||||
|
||||
private static class FlashEffect {
|
||||
final Vec3 explosionPos;
|
||||
final float power;
|
||||
final long startTime;
|
||||
final float maxDurationTicks;
|
||||
final float maxOpacity;
|
||||
final float maxDistance;
|
||||
|
||||
FlashEffect(Vec3 explosionPos, float power) {
|
||||
this.explosionPos = explosionPos;
|
||||
this.power = power;
|
||||
this.startTime = System.currentTimeMillis();
|
||||
this.maxDurationTicks = this.calculateDuration(power) * 20.0f;
|
||||
this.maxOpacity = this.calculateMaxOpacity(power);
|
||||
this.maxDistance = this.calculateMaxDistance(power);
|
||||
}
|
||||
|
||||
private float calculateDuration(float power) {
|
||||
if (power <= 1.0f) {
|
||||
return 0.5f;
|
||||
}
|
||||
if (power <= 5.0f) {
|
||||
return 1.0f;
|
||||
}
|
||||
if (power <= 10.0f) {
|
||||
return 2.5f;
|
||||
}
|
||||
if (power <= 25.0f) {
|
||||
return 3.5f;
|
||||
}
|
||||
return 5.5f;
|
||||
}
|
||||
|
||||
private float calculateMaxDistance(float power) {
|
||||
if (power <= 1.0f) {
|
||||
return 30.0f;
|
||||
}
|
||||
if (power <= 5.0f) {
|
||||
return 30.0f + (power - 1.0f) * 70.0f / 4.0f;
|
||||
}
|
||||
if (power <= 10.0f) {
|
||||
return 100.0f + (power - 5.0f) * 100.0f / 5.0f;
|
||||
}
|
||||
if (power <= 25.0f) {
|
||||
return 200.0f + (power - 10.0f) * 200.0f / 15.0f;
|
||||
}
|
||||
if (power <= 40.0f) {
|
||||
return 400.0f + (power - 25.0f) * 300.0f / 15.0f;
|
||||
}
|
||||
return 700.0f + (power - 40.0f) * 50.0f;
|
||||
}
|
||||
|
||||
private float calculateMaxOpacity(float power) {
|
||||
float baseOpacity = power <= 1.0f ? 0.5f : (power <= 5.0f ? 0.7f : (power <= 10.0f ? 0.9f : 1.0f));
|
||||
return baseOpacity * ((Double)Config.CLIENT.flashMaxOpacity.get()).floatValue();
|
||||
}
|
||||
|
||||
public float getCurrentOpacity(Player player) {
|
||||
long elapsed = System.currentTimeMillis() - this.startTime;
|
||||
float elapsedTicks = (float)elapsed / 50.0f;
|
||||
if (elapsedTicks > this.maxDurationTicks) {
|
||||
return 0.0f;
|
||||
}
|
||||
float progress = elapsedTicks / this.maxDurationTicks;
|
||||
float fadeOpacity = this.maxOpacity * (1.0f - progress * progress);
|
||||
double distance = player.m_146892_().m_82554_(this.explosionPos);
|
||||
float distanceFactor = Math.max(0.0f, 1.0f - (float)distance / this.maxDistance);
|
||||
Vec3 viewVec = player.m_20154_();
|
||||
Vec3 dirToExplosion = this.explosionPos.m_82546_(player.m_146892_()).m_82541_();
|
||||
float dot = (float)viewVec.m_82526_(dirToExplosion);
|
||||
float angleFactor = Math.max(0.0f, dot);
|
||||
if (!this.isVisible(player, this.explosionPos)) {
|
||||
return 0.0f;
|
||||
}
|
||||
return fadeOpacity * distanceFactor * angleFactor;
|
||||
}
|
||||
|
||||
private boolean isVisible(Player player, Vec3 explosionPos) {
|
||||
Vec3 start = player.m_146892_();
|
||||
Vec3 end = explosionPos;
|
||||
ClipContext context = new ClipContext(start, end, ClipContext.Block.VISUAL, ClipContext.Fluid.NONE, (Entity)player);
|
||||
BlockHitResult hit = player.m_9236_().m_45547_(context);
|
||||
if (hit.m_6662_() == HitResult.Type.MISS) {
|
||||
return true;
|
||||
}
|
||||
if (this.power > 10.0f) {
|
||||
int numChecks = Math.max(1, (int)(this.power / 10.0f));
|
||||
for (int i = 1; i <= numChecks; ++i) {
|
||||
Vec3 elevatedStart = start.m_82520_(0.0, (double)(5 * i), 0.0);
|
||||
Vec3 elevatedEnd = end.m_82520_(0.0, (double)(5 * i), 0.0);
|
||||
ClipContext elevatedContext = new ClipContext(elevatedStart, elevatedEnd, ClipContext.Block.VISUAL, ClipContext.Fluid.NONE, (Entity)player);
|
||||
BlockHitResult elevatedHit = player.m_9236_().m_45547_(elevatedContext);
|
||||
if (elevatedHit.m_6662_() != HitResult.Type.MISS) continue;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isFinished() {
|
||||
long elapsed = System.currentTimeMillis() - this.startTime;
|
||||
return (float)elapsed / 50.0f > this.maxDurationTicks;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,663 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul.client;
|
||||
|
||||
import com.vinlanx.explosionoverhaul.Config;
|
||||
import com.vinlanx.explosionoverhaul.ModSounds;
|
||||
import com.vinlanx.explosionoverhaul.client.Blur;
|
||||
import com.vinlanx.explosionoverhaul.client.CameraShakeConcussionEffect;
|
||||
import com.vinlanx.explosionoverhaul.client.DeafnessConcussionEffect;
|
||||
import com.vinlanx.explosionoverhaul.client.LowPassConcussionEffect;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiGraphics;
|
||||
import net.minecraft.client.player.LocalPlayer;
|
||||
import net.minecraft.client.resources.sounds.SimpleSoundInstance;
|
||||
import net.minecraft.client.resources.sounds.SoundInstance;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.sounds.SoundEvent;
|
||||
import net.neoforged.api.distmarker.Dist;
|
||||
import net.neoforged.neoforge.event.TickEvent;
|
||||
import net.neoforged.bus.api.SubscribeEvent;
|
||||
import net.neoforged.fml.common.Mod;
|
||||
import net.neoforged.fml.loading.FMLEnvironment;
|
||||
|
||||
@Mod.EventBusSubscriber(modid="explosionoverhaul", value={Dist.CLIENT})
|
||||
public class ConcussionAudioEffect {
|
||||
public static boolean debugSendDebugMessage = false;
|
||||
public static boolean TestingHudHeart = true;
|
||||
public static float currentBPM = 23.3f;
|
||||
private static double heartbeatCycleTimer = 0.0;
|
||||
private static float heartbeatVisualPulse = 0.0f;
|
||||
private static float explosionBPMMod = 0.0f;
|
||||
private static float jumpBPMMod = 0.0f;
|
||||
private static boolean wasOnGround = true;
|
||||
private static int idleTicks = 0;
|
||||
private static boolean lubTriggered = false;
|
||||
private static boolean dubTriggered = false;
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onClientTick(TickEvent.ClientTickEvent event) {
|
||||
if (event.phase == TickEvent.Phase.END) {
|
||||
Minecraft mc = Minecraft.m_91087_();
|
||||
if (mc.f_91074_ != null && !mc.f_91074_.m_6084_()) {
|
||||
ConcussionAudioEffect.stopAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void stopAll() {
|
||||
Blur.stop();
|
||||
DeafnessConcussionEffect.stop();
|
||||
LowPassConcussionEffect.stop();
|
||||
CameraShakeConcussionEffect.stop();
|
||||
}
|
||||
|
||||
public static void start(float power, double distance, boolean hasDirectLineOfSight, boolean explosionInCave) {
|
||||
LocalPlayer player;
|
||||
LocalPlayer player2;
|
||||
LocalPlayer player3;
|
||||
if (!FMLEnvironment.dist.isClient()) {
|
||||
return;
|
||||
}
|
||||
if (!((Boolean)Config.CLIENT.enableConcussion.get()).booleanValue()) {
|
||||
return;
|
||||
}
|
||||
Minecraft mc = Minecraft.m_91087_();
|
||||
if (mc == null || mc.f_91073_ == null || mc.f_91074_ == null) {
|
||||
return;
|
||||
}
|
||||
double rawPercent = ConcussionAudioEffect.computePercent(power, distance, explosionInCave);
|
||||
if (explosionInCave) {
|
||||
rawPercent = Math.min(100.0, rawPercent * 1.5);
|
||||
}
|
||||
double effectivePercent = hasDirectLineOfSight ? rawPercent : ConcussionAudioEffect.applyOcclusion(rawPercent);
|
||||
double maxDistance = ConcussionAudioEffect.computeMaxDistance(power, explosionInCave);
|
||||
if (rawPercent <= 0.0) {
|
||||
LocalPlayer player4 = mc.f_91074_;
|
||||
if (player4 != null && debugSendDebugMessage) {
|
||||
double metersToExplosion = distance;
|
||||
double onePercentDistance = maxDistance * 0.99;
|
||||
String outMessage = String.format("\u041f\u043e\u0437\u0430 \u0437\u043e\u043d\u043e\u044e \u043f\u043e\u0440\u0430\u0437\u043a\u0438. \u0412\u0456\u0434\u0441\u0442\u0430\u043d\u044c \u0434\u043e \u0432\u0438\u0431\u0443\u0445\u0443: %.1f \u043c. 1%% \u043f\u043e\u0447\u0438\u043d\u0430\u0454\u0442\u044c\u0441\u044f \u0437: %.1f \u043c.", metersToExplosion, onePercentDistance);
|
||||
player4.m_5661_((Component)Component.m_237113_((String)outMessage).m_130940_(ChatFormatting.GRAY), false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
double normalized = Math.max(0.0, Math.min(1.0, effectivePercent / 100.0));
|
||||
float intensity = (float)normalized;
|
||||
if (intensity < 0.01f) {
|
||||
return;
|
||||
}
|
||||
double baseSilentSeconds = ConcussionAudioEffect.computeBaseSilentSeconds(effectivePercent, explosionInCave);
|
||||
double intensityPercent = ConcussionAudioEffect.computeBaseIntensityPercent(effectivePercent);
|
||||
double multiplier = ConcussionAudioEffect.computePowerMultiplier(power);
|
||||
double finalSilentSeconds = baseSilentSeconds * multiplier * (Double)Config.CLIENT.concussionDurationMultiplier.get();
|
||||
double lowpassChance = ConcussionAudioEffect.computeLowpassPowerChance(power, explosionInCave) * (Double)Config.CLIENT.concussionChanceMultiplier.get() * (Double)Config.CLIENT.lowPassChanceMultiplier.get();
|
||||
boolean lowpassRoll = ThreadLocalRandom.current().nextDouble() <= lowpassChance;
|
||||
double chance = ConcussionAudioEffect.computePowerChance(power, explosionInCave) * (Double)Config.CLIENT.concussionChanceMultiplier.get() * (Double)Config.CLIENT.deafnessChanceMultiplier.get();
|
||||
boolean roll = ThreadLocalRandom.current().nextDouble() <= chance;
|
||||
boolean anyAudioEffectActive = roll || lowpassRoll;
|
||||
double baseBlurSeconds = ConcussionAudioEffect.computeBaseBlurSilentSeconds(effectivePercent, explosionInCave);
|
||||
double blurMultiplier = ConcussionAudioEffect.computeBlurPowerMultiplier(power);
|
||||
double finalBlurSeconds = baseBlurSeconds * blurMultiplier * (Double)Config.CLIENT.concussionDurationMultiplier.get();
|
||||
boolean lowpassReduced = false;
|
||||
if (!lowpassRoll) {
|
||||
finalBlurSeconds = roll ? finalSilentSeconds : (finalBlurSeconds /= 3.0);
|
||||
lowpassReduced = true;
|
||||
}
|
||||
int blurSeconds = Math.max(1, (int)Math.round(finalBlurSeconds));
|
||||
double blurIntensityPercent = ConcussionAudioEffect.computeBaseBlurIntensityPercent(effectivePercent);
|
||||
float blurIntensity = (float)(blurIntensityPercent / 100.0);
|
||||
double swayIntensityPercent = ConcussionAudioEffect.computeBaseSwayIntensityPercent(effectivePercent) * (Double)Config.CLIENT.cameraSwayIntensity.get();
|
||||
float swayIntensity = (float)(swayIntensityPercent / 100.0);
|
||||
if (rawPercent > 0.0 && blurIntensity >= 0.01f && anyAudioEffectActive) {
|
||||
float addedBPM = 0.0f;
|
||||
if (rawPercent > 80.0) {
|
||||
addedBPM = 60.0f;
|
||||
} else if (rawPercent > 60.0) {
|
||||
addedBPM = 40.0f;
|
||||
} else if (rawPercent > 30.0) {
|
||||
addedBPM = 20.0f;
|
||||
}
|
||||
explosionBPMMod = Math.min(200.0f, explosionBPMMod + addedBPM);
|
||||
try {
|
||||
LocalPlayer player5;
|
||||
Blur.start(blurSeconds, blurIntensity);
|
||||
if (((Boolean)Config.CLIENT.enableCameraSway.get()).booleanValue()) {
|
||||
CameraShakeConcussionEffect.start(blurSeconds, swayIntensity);
|
||||
}
|
||||
if (debugSendDebugMessage && (player5 = mc.f_91074_) != null) {
|
||||
String reductionInfo = lowpassReduced ? " [LowPass reduced /3]" : "";
|
||||
String blurMsg = String.format("Blur & Sway %.1f m \u2014 activated (Blur: %.2f, Sway: %.2f, Time: %ds%s)", distance, Float.valueOf(blurIntensity), Float.valueOf(swayIntensity), blurSeconds, reductionInfo);
|
||||
player5.m_5661_((Component)Component.m_237113_((String)blurMsg).m_130940_(ChatFormatting.BLUE), false);
|
||||
}
|
||||
}
|
||||
catch (Throwable player5) {}
|
||||
} else if (debugSendDebugMessage && (player3 = mc.f_91074_) != null) {
|
||||
String reason = !anyAudioEffectActive ? "no audio effects" : "out of range";
|
||||
String blurMsg = String.format("Blur %.1f m \u2014 not activated (%s)", distance, reason);
|
||||
player3.m_5661_((Component)Component.m_237113_((String)blurMsg).m_130940_(ChatFormatting.GRAY), false);
|
||||
}
|
||||
int lowpassSeconds = blurSeconds;
|
||||
double lowpassIntensityPercent = ConcussionAudioEffect.computeBaseLowpassIntensityPercent(effectivePercent);
|
||||
float lowpassIntensity = (float)(lowpassIntensityPercent / 100.0);
|
||||
if (lowpassIntensity < 0.01f) {
|
||||
lowpassIntensity = 0.01f;
|
||||
}
|
||||
String lpVisibility = hasDirectLineOfSight ? "\u043f\u0440\u044f\u043c\u0430 \u0432\u0438\u0434\u0438\u043c\u0456\u0441\u0442\u044c" : "\u043f\u0435\u0440\u0435\u0448\u043a\u043e\u0434\u0430";
|
||||
int lowpassIntensityRound = (int)Math.round(lowpassIntensityPercent);
|
||||
if (((Boolean)Config.CLIENT.enableLowPass.get()).booleanValue() && rawPercent > 0.0 && lowpassIntensity >= 0.01f && (lowpassRoll || LowPassConcussionEffect.isActive())) {
|
||||
try {
|
||||
LocalPlayer player6;
|
||||
float finalLpIntensity = lowpassRoll ? lowpassIntensity : 0.0f;
|
||||
int finalLpRound = lowpassRoll ? lowpassIntensityRound : 0;
|
||||
LowPassConcussionEffect.start(lowpassSeconds, finalLpIntensity, effectivePercent, lpVisibility, finalLpRound);
|
||||
if (debugSendDebugMessage && (player6 = mc.f_91074_) != null) {
|
||||
String status = lowpassRoll ? "activated" : "refreshed";
|
||||
String lpMsg = String.format("Low pass %.1f m \u2014 %s (intensity=%.2f chance=%.1f%%)", distance, status, Float.valueOf(finalLpIntensity), lowpassChance * 100.0);
|
||||
player6.m_5661_((Component)Component.m_237113_((String)lpMsg).m_130940_(ChatFormatting.DARK_GREEN), false);
|
||||
}
|
||||
}
|
||||
catch (Throwable finalLpIntensity) {}
|
||||
} else if (debugSendDebugMessage && (player2 = mc.f_91074_) != null) {
|
||||
String reason = rawPercent <= 0.0 || lowpassIntensity < 0.01f ? "out of range" : "chance fail";
|
||||
String lpMsg = String.format("Low pass %.1f m \u2014 not activated (%s)", distance, reason);
|
||||
player2.m_5661_((Component)Component.m_237113_((String)lpMsg).m_130940_(ChatFormatting.GRAY), false);
|
||||
}
|
||||
if (debugSendDebugMessage) {
|
||||
ConcussionAudioEffect.sendDebugMessage(mc, effectivePercent, rawPercent, hasDirectLineOfSight, distance, maxDistance);
|
||||
}
|
||||
if (debugSendDebugMessage && (player = mc.f_91074_) != null) {
|
||||
Object visibility = hasDirectLineOfSight ? "\u043f\u0440\u044f\u043c\u0430 \u0432\u0438\u0434\u0438\u043c\u0456\u0441\u0442\u044c" : "\u043f\u0435\u0440\u0435\u0448\u043a\u043e\u0434\u0430";
|
||||
visibility = (String)visibility + (explosionInCave ? " | \u0432\u0438\u0431\u0443\u0445 \u0443 \u043f\u0435\u0447\u0435\u0440\u0456" : " | \u0432\u0438\u0431\u0443\u0445 \u043d\u0435 \u0432 \u043f\u0435\u0447\u0435\u0440\u0456");
|
||||
visibility = (String)visibility + String.format(" | \u0444\u0456\u043d\u0430\u043b\u044c\u043d\u0438\u0439 %%: %.1f%%", effectivePercent);
|
||||
player.m_5661_((Component)Component.m_237113_((String)visibility).m_130940_(ChatFormatting.GRAY), false);
|
||||
String chanceMsg = String.format("\u0428\u0430\u043d\u0441 \u043a\u043e\u043d\u0442\u0443\u0437\u0456\u0457: %.1f%%", chance * 100.0);
|
||||
player.m_5661_((Component)Component.m_237113_((String)chanceMsg).m_130940_(ChatFormatting.YELLOW), false);
|
||||
double maxDistanceNormal = ConcussionAudioEffect.computeMaxDistance(power, false);
|
||||
double maxDistanceUsed = ConcussionAudioEffect.computeMaxDistance(power, explosionInCave);
|
||||
String distMsg = String.format("\u041c\u0430\u043a\u0441 \u0434\u0438\u0441\u0442\u0430\u043d\u0446\u0456\u044f (\u0437\u0432\u0438\u0447\u0430\u0439\u043d\u0430): %.1f \u043c | (\u0432 \u043f\u0435\u0447\u0435\u0440\u0456): %.1f \u043c | \u0412\u0456\u0434\u0441\u0442\u0430\u043d\u044c \u0434\u043e \u0432\u0438\u0431\u0443\u0445\u0443: %.1f \u043c", maxDistanceNormal, maxDistanceUsed, distance);
|
||||
player.m_5661_((Component)Component.m_237113_((String)distMsg).m_130940_(ChatFormatting.GRAY), false);
|
||||
double baseSilentNormal = ConcussionAudioEffect.computeBaseSilentSeconds(effectivePercent, false);
|
||||
double baseSilentCave = ConcussionAudioEffect.computeBaseSilentSeconds(effectivePercent, true);
|
||||
String silentMsg = String.format("\u0427\u0430\u0441 \u0441\u043a\u0440\u0443\u0447\u0443\u0432\u0430\u043d\u043d\u044f (\u0437\u0432\u0438\u0447\u0430\u0439\u043d\u0438\u0439): %.1fs | (\u0432 \u043f\u0435\u0447\u0435\u0440\u0456): %.1fs | \u0412\u0418\u041a\u041e\u0420\u0418\u0421\u0422\u0410\u041d\u041e: %.1fs", baseSilentNormal, baseSilentCave, baseSilentSeconds * multiplier);
|
||||
player.m_5661_((Component)Component.m_237113_((String)silentMsg).m_130940_(ChatFormatting.GRAY), false);
|
||||
if (roll) {
|
||||
String deafnessMsg = String.format("Deafness %.1f m \u2014 activated (intensity=%.1f%% chance=%.1f%%)", distance, intensityPercent, chance * 100.0);
|
||||
player.m_5661_((Component)Component.m_237113_((String)deafnessMsg).m_130940_(ChatFormatting.RED), false);
|
||||
} else {
|
||||
String deafnessMsg = String.format("Deafness %.1f m \u2014 not activated (chance)", distance);
|
||||
player.m_5661_((Component)Component.m_237113_((String)deafnessMsg).m_130940_(ChatFormatting.GRAY), false);
|
||||
}
|
||||
}
|
||||
if (!roll) {
|
||||
return;
|
||||
}
|
||||
if (!((Boolean)Config.CLIENT.enableDeafness.get()).booleanValue()) {
|
||||
return;
|
||||
}
|
||||
int intensityRound = (int)Math.round(intensityPercent);
|
||||
String visibility = hasDirectLineOfSight ? "\u043f\u0440\u044f\u043c\u0430 \u0432\u0438\u0434\u0438\u043c\u0456\u0441\u0442\u044c" : "\u043f\u0435\u0440\u0435\u0448\u043a\u043e\u0434\u0430";
|
||||
float intensityFromIntensityPercent = (float)(intensityPercent / 100.0);
|
||||
DeafnessConcussionEffect.start(intensityFromIntensityPercent, (float)finalSilentSeconds, effectivePercent, visibility, intensityRound);
|
||||
}
|
||||
|
||||
private static double computePercent(float power, double distance, boolean explosionInCave) {
|
||||
double maxDistance = ConcussionAudioEffect.computeMaxDistance(power, explosionInCave);
|
||||
if (maxDistance <= 0.0) {
|
||||
return 0.0;
|
||||
}
|
||||
double normalized = 1.0 - Math.max(0.0, distance) / maxDistance;
|
||||
return Math.max(0.0, Math.min(1.0, normalized)) * 100.0;
|
||||
}
|
||||
|
||||
private static double computeMaxDistance(float power, boolean explosionInCave) {
|
||||
double[][] points = explosionInCave ? new double[][]{{1.0, 5.0}, {3.0, 10.0}, {10.0, 50.0}, {25.0, 90.0}, {50.0, 150.0}, {80.0, 200.0}, {120.0, 200.0}} : new double[][]{{1.0, 2.0}, {3.0, 5.0}, {10.0, 30.0}, {25.0, 70.0}, {50.0, 100.0}, {80.0, 150.0}, {120.0, 200.0}};
|
||||
double clampedPower = Math.max(points[0][0], Math.min(points[points.length - 1][0], (double)power));
|
||||
for (int i = 1; i < points.length; ++i) {
|
||||
double lowerP = points[i - 1][0];
|
||||
double upperP = points[i][0];
|
||||
if (!(clampedPower <= upperP)) continue;
|
||||
double lowerD = points[i - 1][1];
|
||||
double upperD = points[i][1];
|
||||
double t = (clampedPower - lowerP) / (upperP - lowerP);
|
||||
return lowerD + (upperD - lowerD) * t;
|
||||
}
|
||||
return points[points.length - 1][1];
|
||||
}
|
||||
|
||||
private static double applyOcclusion(double percent) {
|
||||
if (percent >= 80.0) {
|
||||
return percent / 1.2;
|
||||
}
|
||||
if (percent >= 60.0) {
|
||||
return percent / 1.4;
|
||||
}
|
||||
if (percent >= 40.0) {
|
||||
return percent / 1.6;
|
||||
}
|
||||
if (percent >= 20.0) {
|
||||
return percent / 3.0;
|
||||
}
|
||||
if (percent >= 1.0) {
|
||||
return 0.0;
|
||||
}
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
private static void sendDebugMessage(Minecraft mc, double effectivePercent, double rawPercent, boolean hasDirectLineOfSight, double distance, double maxDistance) {
|
||||
LocalPlayer player = mc.f_91074_;
|
||||
if (player == null) {
|
||||
return;
|
||||
}
|
||||
double clamped = Math.max(0.0, Math.min(100.0, effectivePercent));
|
||||
if (rawPercent <= 0.0) {
|
||||
double metersToExplosion = distance;
|
||||
double onePercentDistance = maxDistance * 0.99;
|
||||
String outMessage = String.format("\u041f\u043e\u0437\u0430 \u0437\u043e\u043d\u043e\u044e \u043f\u043e\u0440\u0430\u0437\u043a\u0438. \u0412\u0456\u0434\u0441\u0442\u0430\u043d\u044c \u0434\u043e \u0432\u0438\u0431\u0443\u0445\u0443: %.1f \u043c. 1%% \u043f\u043e\u0447\u0438\u043d\u0430\u0454\u0442\u044c\u0441\u044f \u0437: %.1f \u043c.", metersToExplosion, onePercentDistance);
|
||||
player.m_5661_((Component)Component.m_237113_((String)outMessage).m_130940_(ChatFormatting.GRAY), false);
|
||||
return;
|
||||
}
|
||||
ChatFormatting color = ConcussionAudioEffect.pickColor(clamped);
|
||||
String visibility = hasDirectLineOfSight ? "\u043f\u0440\u044f\u043c\u0430 \u0432\u0438\u0434\u0438\u043c\u0456\u0441\u0442\u044c" : "\u043f\u0435\u0440\u0435\u0448\u043a\u043e\u0434\u0430";
|
||||
String message = String.format("\u041f\u043e\u0442\u0443\u0436\u043d\u0456\u0441\u0442\u044c \u043a\u043e\u043d\u0442\u0443\u0437\u0456\u0457 %.1f%% (%s)", clamped, visibility);
|
||||
player.m_5661_((Component)Component.m_237113_((String)message).m_130940_(color), false);
|
||||
if (!hasDirectLineOfSight && rawPercent > 0.0) {
|
||||
String rawMessage = String.format("(\u0434\u043e \u043f\u0435\u0440\u0435\u0448\u043a\u043e\u0434\u0438: %.1f%%)", Math.max(0.0, Math.min(100.0, rawPercent)));
|
||||
player.m_5661_((Component)Component.m_237113_((String)rawMessage).m_130940_(ChatFormatting.GRAY), false);
|
||||
}
|
||||
}
|
||||
|
||||
private static ChatFormatting pickColor(double percent) {
|
||||
if (percent >= 80.0) {
|
||||
return ChatFormatting.RED;
|
||||
}
|
||||
if (percent >= 60.0) {
|
||||
return ChatFormatting.GOLD;
|
||||
}
|
||||
if (percent >= 40.0) {
|
||||
return ChatFormatting.YELLOW;
|
||||
}
|
||||
if (percent >= 20.0) {
|
||||
return ChatFormatting.AQUA;
|
||||
}
|
||||
if (percent > 0.0) {
|
||||
return ChatFormatting.BLUE;
|
||||
}
|
||||
return ChatFormatting.GRAY;
|
||||
}
|
||||
|
||||
private static double computeBaseSilentSeconds(double effectivePercent, boolean explosionInCave) {
|
||||
if (!explosionInCave) {
|
||||
if (effectivePercent <= 40.0) {
|
||||
return 0.0;
|
||||
}
|
||||
if (effectivePercent > 80.0) {
|
||||
double t = (effectivePercent - 80.0) / 20.0;
|
||||
return 4.0 + 1.0 * t;
|
||||
}
|
||||
if (effectivePercent > 60.0) {
|
||||
double t = (effectivePercent - 60.0) / 20.0;
|
||||
return 2.0 + 2.0 * t;
|
||||
}
|
||||
double t = (effectivePercent - 40.0) / 20.0;
|
||||
return 1.0 + 1.0 * t;
|
||||
}
|
||||
if (effectivePercent <= 20.0) {
|
||||
return 0.0;
|
||||
}
|
||||
if (effectivePercent > 80.0) {
|
||||
double t = (effectivePercent - 80.0) / 20.0;
|
||||
return 7.0 + 3.0 * t;
|
||||
}
|
||||
if (effectivePercent > 60.0) {
|
||||
double t = (effectivePercent - 60.0) / 20.0;
|
||||
return 4.0 + 1.0 * t;
|
||||
}
|
||||
double t = (effectivePercent - 20.0) / 40.0;
|
||||
if (effectivePercent <= 40.0) {
|
||||
double tt = (effectivePercent - 20.0) / 20.0;
|
||||
return 2.0 + 1.0 * tt;
|
||||
}
|
||||
double tt = (effectivePercent - 40.0) / 20.0;
|
||||
return 2.0 + 1.0 * tt;
|
||||
}
|
||||
|
||||
private static double computeBaseIntensityPercent(double effectivePercent) {
|
||||
if (effectivePercent <= 60.0) {
|
||||
return 0.0;
|
||||
}
|
||||
if (effectivePercent <= 70.0) {
|
||||
double t = (effectivePercent - 60.0) / 10.0;
|
||||
return 0.0 + 60.0 * t;
|
||||
}
|
||||
if (effectivePercent <= 85.0) {
|
||||
double t = (effectivePercent - 70.0) / 15.0;
|
||||
return 60.0 + 20.0 * t;
|
||||
}
|
||||
if (effectivePercent <= 90.0) {
|
||||
double t = (effectivePercent - 85.0) / 5.0;
|
||||
return 80.0 + 20.0 * t;
|
||||
}
|
||||
return 100.0;
|
||||
}
|
||||
|
||||
private static double computePowerMultiplier(double power) {
|
||||
double[][] points = new double[][]{{2.0, 1.0}, {5.0, 1.2}, {6.0, 1.4}, {12.0, 1.8}, {13.0, 2.0}, {22.0, 2.3}, {23.0, 2.7}, {50.0, 3.0}, {51.0, 3.2}, {80.0, 5.0}, {120.0, 7.0}};
|
||||
double clamped = Math.max(points[0][0], Math.min(points[points.length - 1][0], power));
|
||||
for (int i = 1; i < points.length; ++i) {
|
||||
double lowerP = points[i - 1][0];
|
||||
double upperP = points[i][0];
|
||||
if (!(clamped <= upperP)) continue;
|
||||
double lowerM = points[i - 1][1];
|
||||
double upperM = points[i][1];
|
||||
double t = (clamped - lowerP) / (upperP - lowerP);
|
||||
return lowerM + (upperM - lowerM) * t;
|
||||
}
|
||||
return points[points.length - 1][1];
|
||||
}
|
||||
|
||||
private static double computePowerChance(double power, boolean explosionInCave) {
|
||||
double[][] points = explosionInCave ? new double[][]{{1.0, 0.25}, {2.0, 0.3}, {3.0, 0.35}, {5.0, 0.4}, {6.0, 0.5}, {10.0, 0.75}, {15.0, 0.9}, {20.0, 1.0}, {120.0, 1.0}} : new double[][]{{1.0, 0.15}, {2.0, 0.15}, {3.0, 0.175}, {5.0, 0.215}, {6.0, 0.225}, {10.0, 0.225}, {11.0, 0.35}, {25.0, 0.4}, {26.0, 0.5}, {34.0, 0.75}, {42.0, 0.9}, {50.0, 1.0}, {120.0, 1.0}};
|
||||
double clamped = Math.max(points[0][0], Math.min(points[points.length - 1][0], power));
|
||||
for (int i = 1; i < points.length; ++i) {
|
||||
double lowerP = points[i - 1][0];
|
||||
double upperP = points[i][0];
|
||||
if (!(clamped <= upperP)) continue;
|
||||
double lowerC = points[i - 1][1];
|
||||
double upperC = points[i][1];
|
||||
double t = (clamped - lowerP) / (upperP - lowerP);
|
||||
return lowerC + (upperC - lowerC) * t;
|
||||
}
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
private static double computeBaseBlurSilentSeconds(double effectivePercent, boolean explosionInCave) {
|
||||
if (!explosionInCave) {
|
||||
if (effectivePercent <= 40.0) {
|
||||
return 0.0;
|
||||
}
|
||||
if (effectivePercent > 80.0) {
|
||||
double t = (effectivePercent - 80.0) / 20.0;
|
||||
return 6.0 + 2.0 * t;
|
||||
}
|
||||
if (effectivePercent > 60.0) {
|
||||
double t = (effectivePercent - 60.0) / 20.0;
|
||||
return 2.0 + 4.0 * t;
|
||||
}
|
||||
double t = (effectivePercent - 40.0) / 20.0;
|
||||
return 0.0 + 2.0 * t;
|
||||
}
|
||||
if (effectivePercent <= 20.0) {
|
||||
return 0.0;
|
||||
}
|
||||
if (effectivePercent > 80.0) {
|
||||
double t = (effectivePercent - 80.0) / 20.0;
|
||||
return 12.0 + 6.0 * t;
|
||||
}
|
||||
if (effectivePercent > 60.0) {
|
||||
double t = (effectivePercent - 60.0) / 20.0;
|
||||
return 6.0 + 2.0 * t;
|
||||
}
|
||||
if (effectivePercent <= 40.0) {
|
||||
double tt = (effectivePercent - 20.0) / 20.0;
|
||||
return 2.0 + 2.0 * Math.max(0.0, Math.min(1.0, tt));
|
||||
}
|
||||
double tt = (effectivePercent - 40.0) / 20.0;
|
||||
return 2.0 + 2.0 * Math.max(0.0, Math.min(1.0, tt));
|
||||
}
|
||||
|
||||
private static double computeBaseBlurIntensityPercent(double effectivePercent) {
|
||||
if (effectivePercent < 60.0) {
|
||||
return 0.0;
|
||||
}
|
||||
double t = (effectivePercent - 60.0) / 40.0;
|
||||
return 1.0 + 49.0 * t;
|
||||
}
|
||||
|
||||
private static double computeBaseSwayIntensityPercent(double effectivePercent) {
|
||||
if (effectivePercent < 50.0) {
|
||||
return 0.0;
|
||||
}
|
||||
double t = (effectivePercent - 50.0) / 50.0;
|
||||
return 100.0 * t;
|
||||
}
|
||||
|
||||
private static double computeBlurPowerMultiplier(double power) {
|
||||
double[][] points = new double[][]{{2.0, 1.0}, {5.0, 1.2}, {6.0, 1.4}, {12.0, 1.8}, {13.0, 2.0}, {22.0, 2.3}, {23.0, 2.7}, {50.0, 3.0}, {51.0, 3.2}, {80.0, 5.0}, {120.0, 7.0}};
|
||||
double clamped = Math.max(points[0][0], Math.min(points[points.length - 1][0], power));
|
||||
for (int i = 1; i < points.length; ++i) {
|
||||
double lowerP = points[i - 1][0];
|
||||
double upperP = points[i][0];
|
||||
if (!(clamped <= upperP)) continue;
|
||||
double lowerM = points[i - 1][1];
|
||||
double upperM = points[i][1];
|
||||
double t = (clamped - lowerP) / (upperP - lowerP);
|
||||
return lowerM + (upperM - lowerM) * t;
|
||||
}
|
||||
return points[points.length - 1][1];
|
||||
}
|
||||
|
||||
public static void renderHeartbeatHUD(GuiGraphics ctx) {
|
||||
if (!((Boolean)Config.CLIENT.showHeartbeatHUD.get()).booleanValue() || !Blur.isActive()) {
|
||||
return;
|
||||
}
|
||||
Minecraft mc = Minecraft.m_91087_();
|
||||
if (mc.f_91074_ == null) {
|
||||
return;
|
||||
}
|
||||
float bps = currentBPM / 60.0f;
|
||||
String text = String.format("%.2f bps (%.1f BPM)", Float.valueOf(bps), Float.valueOf(currentBPM));
|
||||
int x = ctx.m_280182_() - 10;
|
||||
int y = 10;
|
||||
int color = -65536;
|
||||
if (currentBPM < 30.0f) {
|
||||
color = -11141291;
|
||||
} else if (currentBPM < 50.0f) {
|
||||
color = -171;
|
||||
}
|
||||
ctx.m_280056_(mc.f_91062_, text, x - mc.f_91062_.m_92895_(text), y, color, false);
|
||||
}
|
||||
|
||||
public static float getCurrentHeartbeatVisual() {
|
||||
return heartbeatVisualPulse;
|
||||
}
|
||||
|
||||
public static void updateHeartbeat(LocalPlayer player, float blurIntensity) {
|
||||
float healthPercent;
|
||||
boolean isMoving;
|
||||
if (player == null) {
|
||||
return;
|
||||
}
|
||||
if (!Blur.isActive()) {
|
||||
explosionBPMMod *= 0.98f;
|
||||
jumpBPMMod *= 0.98f;
|
||||
if ((currentBPM += (23.3f - currentBPM) * 0.05f) < 24.0f && explosionBPMMod < 0.1f && jumpBPMMod < 0.1f) {
|
||||
currentBPM = 23.3f;
|
||||
explosionBPMMod = 0.0f;
|
||||
jumpBPMMod = 0.0f;
|
||||
heartbeatVisualPulse = 0.0f;
|
||||
return;
|
||||
}
|
||||
}
|
||||
float baseBPM = 23.3f;
|
||||
boolean bl = isMoving = player.m_20184_().m_165925_() > 0.001;
|
||||
if (isMoving) {
|
||||
if (player.m_20142_()) {
|
||||
baseBPM = 50.0f;
|
||||
if (!player.m_20096_()) {
|
||||
baseBPM = 60.0f;
|
||||
}
|
||||
} else {
|
||||
baseBPM = 35.0f;
|
||||
}
|
||||
}
|
||||
if ((healthPercent = player.m_21223_() / player.m_21233_()) < 0.1f) {
|
||||
baseBPM += 63.3f;
|
||||
} else if (healthPercent < 0.3f) {
|
||||
baseBPM += 43.3f;
|
||||
}
|
||||
if (!player.m_20096_() && wasOnGround && isMoving) {
|
||||
jumpBPMMod = Math.min(13.3f, jumpBPMMod + 3.3f);
|
||||
}
|
||||
wasOnGround = player.m_20096_();
|
||||
jumpBPMMod *= 0.99f;
|
||||
explosionBPMMod *= 0.995f;
|
||||
if (player.f_19789_ > 3.0f) {
|
||||
baseBPM += Math.min(16.6f, player.f_19789_ * 1.6f);
|
||||
}
|
||||
if (player.m_20146_() <= 0) {
|
||||
baseBPM += 5.0f;
|
||||
}
|
||||
if (player.m_6047_()) {
|
||||
baseBPM -= 3.3f;
|
||||
}
|
||||
if (!isMoving) {
|
||||
if (++idleTicks >= 60) {
|
||||
baseBPM -= 1.6f;
|
||||
idleTicks = 0;
|
||||
}
|
||||
} else {
|
||||
idleTicks = 0;
|
||||
}
|
||||
float finalTarget = baseBPM + jumpBPMMod + explosionBPMMod;
|
||||
if ((finalTarget = Math.max(20.0f, Math.min(130.0f, finalTarget))) > currentBPM) {
|
||||
float rampSpeed = explosionBPMMod > 5.0f || Blur.isActive() ? 0.4f : 0.15f;
|
||||
currentBPM += (finalTarget - currentBPM) * rampSpeed;
|
||||
} else {
|
||||
currentBPM += (finalTarget - currentBPM) * 0.04f;
|
||||
}
|
||||
double cycleSeconds = 60.0 / (double)Math.max(5.0f, currentBPM);
|
||||
heartbeatCycleTimer += 0.05;
|
||||
if (heartbeatCycleTimer >= cycleSeconds) {
|
||||
heartbeatCycleTimer -= cycleSeconds;
|
||||
lubTriggered = false;
|
||||
dubTriggered = false;
|
||||
}
|
||||
double t = heartbeatCycleTimer;
|
||||
float pulse = 0.0f;
|
||||
double lubEnd = cycleSeconds * 0.35;
|
||||
double pause1End = cycleSeconds * 0.45;
|
||||
double dubEnd = cycleSeconds * 0.7;
|
||||
if (t < lubEnd) {
|
||||
s = (float)Math.sin(t / lubEnd * Math.PI);
|
||||
pulse = (float)Math.pow(s, 1.2);
|
||||
if (!lubTriggered) {
|
||||
lubTriggered = true;
|
||||
if (blurIntensity >= 0.1f && ((Boolean)Config.CLIENT.enableHeartbeatPulse.get()).booleanValue()) {
|
||||
try {
|
||||
Minecraft mc = Minecraft.m_91087_();
|
||||
if (mc != null) {
|
||||
mc.m_91106_().m_120367_((SoundInstance)SimpleSoundInstance.m_119755_((SoundEvent)((SoundEvent)ModSounds.HEART_LAB.get()), (float)1.0f, (float)100.0f));
|
||||
}
|
||||
}
|
||||
catch (Throwable mc) {}
|
||||
}
|
||||
}
|
||||
} else if (t > pause1End && t < dubEnd) {
|
||||
s = (float)Math.sin((t - pause1End) / (dubEnd - pause1End) * Math.PI);
|
||||
pulse = (float)Math.pow(s, 1.2) * 0.7f;
|
||||
if (!dubTriggered) {
|
||||
dubTriggered = true;
|
||||
if (blurIntensity >= 0.1f && ((Boolean)Config.CLIENT.enableHeartbeatPulse.get()).booleanValue()) {
|
||||
try {
|
||||
Minecraft mc = Minecraft.m_91087_();
|
||||
if (mc != null) {
|
||||
mc.m_91106_().m_120367_((SoundInstance)SimpleSoundInstance.m_119755_((SoundEvent)((SoundEvent)ModSounds.HEART_DAB.get()), (float)1.0f, (float)100.0f));
|
||||
}
|
||||
}
|
||||
catch (Throwable throwable) {
|
||||
// empty catch block
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((healthPercent < 0.05f || explosionBPMMod > 80.0f && t < 2.0) && ThreadLocalRandom.current().nextDouble() < 0.03) {
|
||||
heartbeatCycleTimer += 0.08;
|
||||
}
|
||||
float pulseScale = 0.3f + blurIntensity * 1.5f;
|
||||
heartbeatVisualPulse = pulse * pulseScale;
|
||||
}
|
||||
|
||||
private static double computeBaseLowpassSilentSeconds(double effectivePercent, boolean explosionInCave) {
|
||||
if (!explosionInCave) {
|
||||
if (effectivePercent <= 40.0) {
|
||||
return 0.0;
|
||||
}
|
||||
if (effectivePercent > 80.0) {
|
||||
double t = (effectivePercent - 80.0) / 20.0;
|
||||
return 8.0 + 2.0 * t;
|
||||
}
|
||||
if (effectivePercent > 60.0) {
|
||||
double t = (effectivePercent - 60.0) / 20.0;
|
||||
return 4.0 + 4.0 * t;
|
||||
}
|
||||
double t = (effectivePercent - 40.0) / 20.0;
|
||||
return 2.0 + 2.0 * t;
|
||||
}
|
||||
if (effectivePercent <= 20.0) {
|
||||
return 0.0;
|
||||
}
|
||||
if (effectivePercent > 80.0) {
|
||||
double t = (effectivePercent - 80.0) / 20.0;
|
||||
return 14.0 + 6.0 * t;
|
||||
}
|
||||
if (effectivePercent > 60.0) {
|
||||
double t = (effectivePercent - 60.0) / 20.0;
|
||||
return 8.0 + 2.0 * t;
|
||||
}
|
||||
if (effectivePercent <= 40.0) {
|
||||
double tt = (effectivePercent - 20.0) / 20.0;
|
||||
return 4.0 + 2.0 * Math.max(0.0, Math.min(1.0, tt));
|
||||
}
|
||||
double tt = (effectivePercent - 40.0) / 20.0;
|
||||
return 4.0 + 2.0 * Math.max(0.0, Math.min(1.0, tt));
|
||||
}
|
||||
|
||||
private static double computeBaseLowpassIntensityPercent(double effectivePercent) {
|
||||
if (effectivePercent <= 40.0) {
|
||||
return 0.0;
|
||||
}
|
||||
if (effectivePercent <= 50.0) {
|
||||
double t = (effectivePercent - 40.0) / 10.0;
|
||||
return 0.0 + 70.0 * t;
|
||||
}
|
||||
if (effectivePercent <= 70.0) {
|
||||
double t = (effectivePercent - 50.0) / 20.0;
|
||||
return 70.0 + 30.0 * t;
|
||||
}
|
||||
return 100.0;
|
||||
}
|
||||
|
||||
private static double computeLowpassPowerMultiplier(double power) {
|
||||
double[][] points = new double[][]{{2.0, 1.0}, {5.0, 1.2}, {6.0, 1.4}, {12.0, 1.8}, {13.0, 2.0}, {22.0, 2.3}, {23.0, 2.7}, {50.0, 3.0}, {51.0, 3.2}, {80.0, 5.0}, {120.0, 7.0}};
|
||||
double clamped = Math.max(points[0][0], Math.min(points[points.length - 1][0], power));
|
||||
for (int i = 1; i < points.length; ++i) {
|
||||
double lowerP = points[i - 1][0];
|
||||
double upperP = points[i][0];
|
||||
if (!(clamped <= upperP)) continue;
|
||||
double lowerM = points[i - 1][1];
|
||||
double upperM = points[i][1];
|
||||
double t = (clamped - lowerP) / (upperP - lowerP);
|
||||
return lowerM + (upperM - lowerM) * t;
|
||||
}
|
||||
return points[points.length - 1][1];
|
||||
}
|
||||
|
||||
private static double computeLowpassPowerChance(double power, boolean explosionInCave) {
|
||||
double[][] points = explosionInCave ? new double[][]{{1.0, 0.5}, {2.0, 0.6}, {3.0, 0.7}, {5.0, 0.8}, {6.0, 0.95}, {120.0, 1.0}} : new double[][]{{1.0, 0.3}, {2.0, 0.3}, {3.0, 0.35}, {5.0, 0.43}, {6.0, 0.45}, {10.0, 0.45}, {11.0, 0.7}, {25.0, 0.8}, {26.0, 1.0}, {120.0, 1.0}};
|
||||
double clamped = Math.max(points[0][0], Math.min(points[points.length - 1][0], power));
|
||||
for (int i = 1; i < points.length; ++i) {
|
||||
double lowerP = points[i - 1][0];
|
||||
double upperP = points[i][0];
|
||||
if (!(clamped <= upperP)) continue;
|
||||
double lowerC = points[i - 1][1];
|
||||
double upperC = points[i][1];
|
||||
double t = (clamped - lowerP) / (upperP - lowerP);
|
||||
return lowerC + (upperC - lowerC) * t;
|
||||
}
|
||||
return 1.0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul.client;
|
||||
|
||||
import com.vinlanx.explosionoverhaul.ModSounds;
|
||||
import com.vinlanx.explosionoverhaul.client.Blur;
|
||||
import com.vinlanx.explosionoverhaul.client.DeafnessConcussionEffect;
|
||||
import com.vinlanx.explosionoverhaul.client.FadingMusicInstance;
|
||||
import com.vinlanx.explosionoverhaul.client.LowPassConcussionEffect;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.resources.sounds.SoundInstance;
|
||||
import net.minecraft.sounds.SoundEvent;
|
||||
import net.minecraft.sounds.SoundSource;
|
||||
import net.neoforged.api.distmarker.Dist;
|
||||
import net.neoforged.api.distmarker.OnlyIn;
|
||||
import net.neoforged.neoforge.event.TickEvent;
|
||||
import net.neoforged.bus.api.SubscribeEvent;
|
||||
import net.neoforged.fml.common.Mod;
|
||||
|
||||
@OnlyIn(value=Dist.CLIENT)
|
||||
@Mod.EventBusSubscriber(modid="explosionoverhaul", value={Dist.CLIENT})
|
||||
public class ConcussionSoundManager {
|
||||
private static FadingMusicInstance currentLowSound = null;
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onClientTick(TickEvent.ClientTickEvent event) {
|
||||
if (event.phase != TickEvent.Phase.END) {
|
||||
return;
|
||||
}
|
||||
Minecraft mc = Minecraft.m_91087_();
|
||||
if (mc.f_91073_ == null || mc.f_91074_ == null) {
|
||||
if (currentLowSound != null) {
|
||||
mc.m_91106_().m_120399_((SoundInstance)currentLowSound);
|
||||
currentLowSound = null;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (mc.m_91104_()) {
|
||||
return;
|
||||
}
|
||||
boolean deafness = DeafnessConcussionEffect.isActive();
|
||||
boolean lowpass = LowPassConcussionEffect.isActive();
|
||||
boolean blur = Blur.isActive();
|
||||
float targetVolume = 0.0f;
|
||||
if (blur) {
|
||||
if (deafness) {
|
||||
targetVolume = 1.0f;
|
||||
} else if (lowpass) {
|
||||
targetVolume = 0.4f;
|
||||
}
|
||||
}
|
||||
if (targetVolume > 0.0f) {
|
||||
if (currentLowSound == null || !mc.m_91106_().m_120403_((SoundInstance)currentLowSound)) {
|
||||
currentLowSound = new FadingMusicInstance((SoundEvent)ModSounds.LOW_SOUND.get(), 0.01f, SoundSource.MASTER);
|
||||
currentLowSound.fadeTo(targetVolume, 1.0f);
|
||||
mc.m_91106_().m_120367_((SoundInstance)currentLowSound);
|
||||
} else if (Math.abs(currentLowSound.getCurrentVolume() - targetVolume) > 0.01f && !currentLowSound.hasFinishedFading()) {
|
||||
currentLowSound.fadeTo(targetVolume, 0.5f);
|
||||
}
|
||||
} else if (currentLowSound != null && mc.m_91106_().m_120403_((SoundInstance)currentLowSound) && !currentLowSound.hasFinishedFading()) {
|
||||
currentLowSound.fadeOutAndStop(1.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,346 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul.client;
|
||||
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.mojang.blaze3d.vertex.BufferBuilder;
|
||||
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
|
||||
import com.mojang.blaze3d.vertex.Tesselator;
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||
import com.mojang.blaze3d.vertex.VertexFormat;
|
||||
import com.vinlanx.explosionoverhaul.Config;
|
||||
import com.vinlanx.explosionoverhaul.CustomGlowParticleOptions;
|
||||
import com.vinlanx.explosionoverhaul.client.ExplosionTextureManager;
|
||||
import com.vinlanx.explosionoverhaul.client.ExplosionWindController;
|
||||
import net.minecraft.client.Camera;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.client.particle.ParticleRenderType;
|
||||
import net.minecraft.client.particle.TextureSheetParticle;
|
||||
import net.minecraft.client.renderer.GameRenderer;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.joml.Quaternionf;
|
||||
import org.joml.Quaternionfc;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
public class CustomGlowParticle
|
||||
extends TextureSheetParticle {
|
||||
private final float power;
|
||||
private final float initialQuadSize;
|
||||
private final int animationDuration;
|
||||
private final int animationType;
|
||||
private final float centerY;
|
||||
private final float maxRadius;
|
||||
private float currentHeightPercent;
|
||||
private final int peakFireEndTick;
|
||||
private final int fireTransitionEndTick;
|
||||
private final int smokeStartTick;
|
||||
private static final int GLOW_FRAME_COUNT = 239;
|
||||
private static final int SGLOW_FRAME_COUNT = 224;
|
||||
private static final int FRAMES_PER_SHEET = 64;
|
||||
private static final int FRAMES_PER_ROW = 8;
|
||||
private int baseSheetIndex;
|
||||
private int baseFrameOnSheet;
|
||||
private int emissiveSheetIndex;
|
||||
private int emissiveFrameOnSheet;
|
||||
|
||||
public CustomGlowParticle(ClientLevel pLevel, double pX, double pY, double pZ, double pXSpeed, double pYSpeed, double pZSpeed, CustomGlowParticleOptions options) {
|
||||
super(pLevel, pX, pY, pZ, pXSpeed, pYSpeed, pZSpeed);
|
||||
int fadeOutDurationTicks;
|
||||
this.f_172258_ = 0.98f;
|
||||
this.f_107226_ = 0.0f;
|
||||
this.f_107215_ = pXSpeed;
|
||||
this.f_107216_ = pYSpeed;
|
||||
this.f_107217_ = pZSpeed;
|
||||
this.power = options.getPower();
|
||||
this.initialQuadSize = options.getScale();
|
||||
this.animationType = options.getAnimationType();
|
||||
this.f_107663_ = this.initialQuadSize;
|
||||
this.centerY = options.getCenterY();
|
||||
this.maxRadius = options.getMaxRadius();
|
||||
this.currentHeightPercent = options.getHeightPercent();
|
||||
if (this.power <= 1.0f) {
|
||||
this.animationDuration = 40;
|
||||
fadeOutDurationTicks = 40;
|
||||
} else if (this.power <= 10.0f) {
|
||||
this.animationDuration = this.interpolate(this.power, 1.0f, 40.0f, 10.0f, 100.0f);
|
||||
fadeOutDurationTicks = this.interpolate(this.power, 1.0f, 40.0f, 10.0f, 60.0f);
|
||||
} else if (this.power <= 60.0f) {
|
||||
this.animationDuration = this.interpolate(this.power, 10.0f, 100.0f, 60.0f, 140.0f);
|
||||
fadeOutDurationTicks = this.interpolate(this.power, 10.0f, 60.0f, 60.0f, 80.0f);
|
||||
} else if (this.power <= 100.0f) {
|
||||
this.animationDuration = this.interpolate(this.power, 60.0f, 140.0f, 100.0f, 200.0f);
|
||||
fadeOutDurationTicks = this.interpolate(this.power, 60.0f, 80.0f, 100.0f, 120.0f);
|
||||
} else {
|
||||
this.animationDuration = 200;
|
||||
fadeOutDurationTicks = 120;
|
||||
}
|
||||
this.f_107225_ = this.animationDuration + fadeOutDurationTicks;
|
||||
float powerFraction = Mth.m_14036_((float)(this.power / 100.0f), (float)0.0f, (float)1.0f);
|
||||
float totalFirePercent = Mth.m_14179_((float)powerFraction, (float)0.02f, (float)0.2f);
|
||||
float cooldownToSmokePercent = Mth.m_14179_((float)powerFraction, (float)0.04f, (float)0.08f);
|
||||
int totalFireDuration = (int)((float)this.f_107225_ * totalFirePercent);
|
||||
this.peakFireEndTick = (int)((float)totalFireDuration * 0.9f);
|
||||
this.fireTransitionEndTick = totalFireDuration;
|
||||
int cooldownDuration = (int)((float)this.f_107225_ * cooldownToSmokePercent);
|
||||
this.smokeStartTick = this.fireTransitionEndTick + cooldownDuration;
|
||||
if (Config.CLIENT.particleRenderMode.get() == Config.Client.ParticleRenderMode.VANILA) {
|
||||
this.f_107230_ = 1.0f;
|
||||
this.f_107227_ = 1.0f;
|
||||
this.f_107228_ = 0.85f;
|
||||
this.f_107229_ = 0.5f;
|
||||
}
|
||||
}
|
||||
|
||||
public void m_5989_() {
|
||||
double targetSpeed;
|
||||
this.f_107209_ = this.f_107212_;
|
||||
this.f_107210_ = this.f_107213_;
|
||||
this.f_107211_ = this.f_107214_;
|
||||
if (this.f_107224_++ >= this.f_107225_) {
|
||||
this.m_107274_();
|
||||
return;
|
||||
}
|
||||
if (Config.CLIENT.particleRenderMode.get() == Config.Client.ParticleRenderMode.VANILA) {
|
||||
this.tickVanila();
|
||||
} else if (Config.CLIENT.particleRenderMode.get() == Config.Client.ParticleRenderMode.REALISTIC_2) {
|
||||
this.tickRealistic2();
|
||||
} else {
|
||||
this.tickRealistic();
|
||||
}
|
||||
this.m_6257_(this.f_107215_, this.f_107216_, this.f_107217_);
|
||||
this.f_107215_ *= (double)this.f_172258_;
|
||||
this.f_107216_ *= (double)this.f_172258_;
|
||||
this.f_107217_ *= (double)this.f_172258_;
|
||||
float heightPercent = this.updateHeightPercent();
|
||||
Vec3 direction = ExplosionWindController.getWindDirection();
|
||||
if (direction != Vec3.f_82478_ && (targetSpeed = ExplosionWindController.computeGlowSpeed(heightPercent)) > 0.0) {
|
||||
double targetX = direction.f_82479_ * targetSpeed;
|
||||
double targetZ = direction.f_82481_ * targetSpeed;
|
||||
this.f_107215_ += (targetX - this.f_107215_) * 0.1;
|
||||
this.f_107217_ += (targetZ - this.f_107217_) * 0.1;
|
||||
}
|
||||
}
|
||||
|
||||
private void tickVanila() {
|
||||
this.baseSheetIndex = 0;
|
||||
this.f_107663_ = this.initialQuadSize;
|
||||
if (this.f_107224_ < this.peakFireEndTick) {
|
||||
this.f_107230_ = 1.0f;
|
||||
this.f_107227_ = 1.0f;
|
||||
this.f_107228_ = 0.85f;
|
||||
this.f_107229_ = 0.5f;
|
||||
} else if (this.f_107224_ < this.fireTransitionEndTick) {
|
||||
float progress = (float)(this.f_107224_ - this.peakFireEndTick) / (float)(this.fireTransitionEndTick - this.peakFireEndTick);
|
||||
this.f_107230_ = 1.0f;
|
||||
this.f_107227_ = 1.0f;
|
||||
this.f_107228_ = Mth.m_14179_((float)progress, (float)0.85f, (float)0.5f);
|
||||
this.f_107229_ = Mth.m_14179_((float)progress, (float)0.5f, (float)0.1f);
|
||||
} else if (this.f_107224_ < this.smokeStartTick) {
|
||||
float progress = (float)(this.f_107224_ - this.fireTransitionEndTick) / (float)(this.smokeStartTick - this.fireTransitionEndTick);
|
||||
float smokeCol = 0.15f;
|
||||
this.f_107227_ = Mth.m_14179_((float)progress, (float)1.0f, (float)(smokeCol + 0.1f));
|
||||
this.f_107228_ = Mth.m_14179_((float)progress, (float)0.5f, (float)smokeCol);
|
||||
this.f_107229_ = Mth.m_14179_((float)progress, (float)0.1f, (float)smokeCol);
|
||||
this.f_107230_ = Mth.m_14179_((float)progress, (float)1.0f, (float)0.9f);
|
||||
} else {
|
||||
float progress = (float)(this.f_107224_ - this.smokeStartTick) / (float)(this.f_107225_ - this.smokeStartTick);
|
||||
float finalSmokeCol = 0.05f;
|
||||
this.f_107228_ = this.f_107229_ = Mth.m_14179_((float)progress, (float)0.15f, (float)finalSmokeCol);
|
||||
this.f_107227_ = this.f_107229_;
|
||||
this.f_107230_ = 0.9f * (1.0f - progress * progress * progress);
|
||||
}
|
||||
}
|
||||
|
||||
private void tickRealistic2() {
|
||||
int frameIndex;
|
||||
int emissiveSheetStart;
|
||||
int baseSheetStart;
|
||||
int frameCountForAnim;
|
||||
this.f_107663_ = this.initialQuadSize * 2.0f;
|
||||
if (this.animationType == 2) {
|
||||
frameCountForAnim = 224;
|
||||
baseSheetStart = 18;
|
||||
emissiveSheetStart = 22;
|
||||
} else if (this.animationType == 1) {
|
||||
frameCountForAnim = 239;
|
||||
baseSheetStart = 10;
|
||||
emissiveSheetStart = 14;
|
||||
} else {
|
||||
frameCountForAnim = 239;
|
||||
baseSheetStart = 2;
|
||||
emissiveSheetStart = 6;
|
||||
}
|
||||
if (this.f_107224_ < this.animationDuration) {
|
||||
float animProgress = (float)this.f_107224_ / (float)this.animationDuration;
|
||||
float easedProgress = 1.0f - (float)Math.pow(1.0f - animProgress, 3.0);
|
||||
frameIndex = (int)(easedProgress * (float)(frameCountForAnim - 1));
|
||||
this.f_107230_ = 1.0f;
|
||||
} else {
|
||||
frameIndex = frameCountForAnim - 1;
|
||||
int fadeDuration = this.f_107225_ - this.animationDuration;
|
||||
int ageInFade = this.f_107224_ - this.animationDuration;
|
||||
this.f_107230_ = 1.0f - (float)ageInFade / (float)fadeDuration;
|
||||
}
|
||||
frameIndex = Mth.m_14045_((int)frameIndex, (int)0, (int)(frameCountForAnim - 1));
|
||||
this.baseSheetIndex = baseSheetStart + frameIndex / 64;
|
||||
this.baseFrameOnSheet = frameIndex % 64;
|
||||
this.emissiveSheetIndex = emissiveSheetStart + frameIndex / 64;
|
||||
this.emissiveFrameOnSheet = frameIndex % 64;
|
||||
}
|
||||
|
||||
private void tickRealistic() {
|
||||
int frameIndex;
|
||||
int emissiveSheetStart;
|
||||
int baseSheetStart;
|
||||
int frameCountForAnim;
|
||||
if (this.animationType == 2) {
|
||||
frameCountForAnim = 224;
|
||||
baseSheetStart = 18;
|
||||
emissiveSheetStart = 22;
|
||||
} else if (this.animationType == 1) {
|
||||
frameCountForAnim = 239;
|
||||
baseSheetStart = 10;
|
||||
emissiveSheetStart = 14;
|
||||
} else {
|
||||
frameCountForAnim = 239;
|
||||
baseSheetStart = 2;
|
||||
emissiveSheetStart = 6;
|
||||
}
|
||||
if (this.f_107224_ < this.animationDuration) {
|
||||
float animProgress = (float)this.f_107224_ / (float)this.animationDuration;
|
||||
float easedProgress = 1.0f - (float)Math.pow(1.0f - animProgress, 3.0);
|
||||
frameIndex = (int)(easedProgress * (float)(frameCountForAnim - 1));
|
||||
this.f_107230_ = 1.0f;
|
||||
} else {
|
||||
frameIndex = frameCountForAnim - 1;
|
||||
int fadeDuration = this.f_107225_ - this.animationDuration;
|
||||
int ageInFade = this.f_107224_ - this.animationDuration;
|
||||
this.f_107230_ = 1.0f - (float)ageInFade / (float)fadeDuration;
|
||||
}
|
||||
frameIndex = Mth.m_14045_((int)frameIndex, (int)0, (int)(frameCountForAnim - 1));
|
||||
this.baseSheetIndex = baseSheetStart + frameIndex / 64;
|
||||
this.baseFrameOnSheet = frameIndex % 64;
|
||||
this.emissiveSheetIndex = emissiveSheetStart + frameIndex / 64;
|
||||
this.emissiveFrameOnSheet = frameIndex % 64;
|
||||
}
|
||||
|
||||
public void m_5744_(VertexConsumer pBuffer, Camera pRenderInfo, float pPartialTicks) {
|
||||
Vector3f[] avector3f;
|
||||
Vec3 vec3 = pRenderInfo.m_90583_();
|
||||
float f = (float)(Mth.m_14139_((double)pPartialTicks, (double)this.f_107209_, (double)this.f_107212_) - vec3.m_7096_());
|
||||
float f1 = (float)(Mth.m_14139_((double)pPartialTicks, (double)this.f_107210_, (double)this.f_107213_) - vec3.m_7098_());
|
||||
float f2 = (float)(Mth.m_14139_((double)pPartialTicks, (double)this.f_107211_, (double)this.f_107214_) - vec3.m_7094_());
|
||||
Quaternionf quaternion = new Quaternionf((Quaternionfc)pRenderInfo.m_253121_());
|
||||
if (this.f_107231_ != 0.0f) {
|
||||
float f3 = Mth.m_14179_((float)pPartialTicks, (float)this.f_107204_, (float)this.f_107231_);
|
||||
quaternion.rotateZ(f3);
|
||||
}
|
||||
if (this.animationType == 2) {
|
||||
float aspectRatio = 0.5629139f;
|
||||
avector3f = new Vector3f[]{new Vector3f(-0.5629139f, -1.0f, 0.0f), new Vector3f(-0.5629139f, 1.0f, 0.0f), new Vector3f(0.5629139f, 1.0f, 0.0f), new Vector3f(0.5629139f, -1.0f, 0.0f)};
|
||||
} else {
|
||||
avector3f = new Vector3f[]{new Vector3f(-1.0f, -1.0f, 0.0f), new Vector3f(-1.0f, 1.0f, 0.0f), new Vector3f(1.0f, 1.0f, 0.0f), new Vector3f(1.0f, -1.0f, 0.0f)};
|
||||
}
|
||||
float f4 = this.m_5902_(pPartialTicks);
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
Vector3f vector3f = avector3f[i];
|
||||
vector3f.rotate((Quaternionfc)quaternion);
|
||||
vector3f.mul(f4);
|
||||
vector3f.add(f, f1, f2);
|
||||
}
|
||||
int worldLight = this.m_6355_(pPartialTicks);
|
||||
int frameToRender = Config.CLIENT.particleRenderMode.get() == Config.Client.ParticleRenderMode.VANILA ? 0 : this.baseFrameOnSheet;
|
||||
ResourceLocation baseTexture = ExplosionTextureManager.getInstance().getTexture(this.baseSheetIndex);
|
||||
this.renderFrame(avector3f, baseTexture, frameToRender, this.f_107227_, this.f_107228_, this.f_107229_, this.f_107230_, worldLight);
|
||||
if (Config.CLIENT.particleRenderMode.get() == Config.Client.ParticleRenderMode.REALISTIC || Config.CLIENT.particleRenderMode.get() == Config.Client.ParticleRenderMode.REALISTIC_2) {
|
||||
ResourceLocation emissiveTexture = ExplosionTextureManager.getInstance().getTexture(this.emissiveSheetIndex);
|
||||
int fullBright = 240;
|
||||
this.renderFrame(avector3f, emissiveTexture, this.emissiveFrameOnSheet, this.f_107227_, this.f_107228_, this.f_107229_, this.f_107230_, fullBright);
|
||||
} else if (this.f_107224_ < this.smokeStartTick) {
|
||||
ResourceLocation emissiveTexture = ExplosionTextureManager.getInstance().getTexture(1);
|
||||
int fullBright = 240;
|
||||
this.renderFrame(avector3f, emissiveTexture, 0, this.f_107227_, this.f_107228_, this.f_107229_, this.f_107230_ * 0.8f, fullBright);
|
||||
}
|
||||
}
|
||||
|
||||
private void renderFrame(Vector3f[] vertices, ResourceLocation texture, int frame, float r, float g, float b, float a, int light) {
|
||||
float v1;
|
||||
float u1;
|
||||
float v0;
|
||||
float u0;
|
||||
if (texture == null) {
|
||||
return;
|
||||
}
|
||||
RenderSystem.setShader(GameRenderer::m_172829_);
|
||||
RenderSystem.setShaderTexture((int)0, (ResourceLocation)texture);
|
||||
RenderSystem.enableDepthTest();
|
||||
RenderSystem.enableBlend();
|
||||
RenderSystem.defaultBlendFunc();
|
||||
RenderSystem.depthMask((boolean)true);
|
||||
Tesselator tesselator = Tesselator.m_85913_();
|
||||
BufferBuilder buffer = tesselator.m_85915_();
|
||||
buffer.m_166779_(VertexFormat.Mode.QUADS, DefaultVertexFormat.f_85813_);
|
||||
if (frame == 0 && Config.CLIENT.particleRenderMode.get() == Config.Client.ParticleRenderMode.VANILA) {
|
||||
u0 = 0.0f;
|
||||
v0 = 0.0f;
|
||||
u1 = 1.0f;
|
||||
v1 = 1.0f;
|
||||
} else {
|
||||
float frameUWidth = 0.125f;
|
||||
float frameVHeight = 0.125f;
|
||||
int col = frame % 8;
|
||||
int row = frame / 8;
|
||||
u0 = (float)col * frameUWidth;
|
||||
v0 = (float)row * frameVHeight;
|
||||
u1 = u0 + frameUWidth;
|
||||
v1 = v0 + frameVHeight;
|
||||
}
|
||||
buffer.m_5483_((double)vertices[0].x(), (double)vertices[0].y(), (double)vertices[0].z()).m_7421_(u0, v1).m_85950_(r, g, b, a).m_85969_(light).m_5752_();
|
||||
buffer.m_5483_((double)vertices[1].x(), (double)vertices[1].y(), (double)vertices[1].z()).m_7421_(u0, v0).m_85950_(r, g, b, a).m_85969_(light).m_5752_();
|
||||
buffer.m_5483_((double)vertices[2].x(), (double)vertices[2].y(), (double)vertices[2].z()).m_7421_(u1, v0).m_85950_(r, g, b, a).m_85969_(light).m_5752_();
|
||||
buffer.m_5483_((double)vertices[3].x(), (double)vertices[3].y(), (double)vertices[3].z()).m_7421_(u1, v1).m_85950_(r, g, b, a).m_85969_(light).m_5752_();
|
||||
tesselator.m_85914_();
|
||||
}
|
||||
|
||||
public ParticleRenderType m_7556_() {
|
||||
return ParticleRenderType.f_107433_;
|
||||
}
|
||||
|
||||
private int interpolate(float power, float p1, float v1, float p2, float v2) {
|
||||
if (p2 == p1) {
|
||||
return (int)v1;
|
||||
}
|
||||
float fraction = (power - p1) / (p2 - p1);
|
||||
return (int)(v1 + fraction * (v2 - v1));
|
||||
}
|
||||
|
||||
private float updateHeightPercent() {
|
||||
if (this.maxRadius <= 0.0f) {
|
||||
return 0.5f;
|
||||
}
|
||||
return Math.max(0.25f, this.currentHeightPercent);
|
||||
}
|
||||
|
||||
public int m_6355_(float pPartialTick) {
|
||||
if (Config.CLIENT.particleRenderMode.get() == Config.Client.ParticleRenderMode.VANILA) {
|
||||
float currentAge = (float)this.f_107224_ + pPartialTick;
|
||||
if (currentAge < (float)this.fireTransitionEndTick) {
|
||||
return 240;
|
||||
}
|
||||
if (currentAge > (float)this.smokeStartTick) {
|
||||
return super.m_6355_(pPartialTick);
|
||||
}
|
||||
float progress = (currentAge - (float)this.fireTransitionEndTick) / (float)(this.smokeStartTick - this.fireTransitionEndTick);
|
||||
int packedAmbient = super.m_6355_(pPartialTick);
|
||||
int skyLightAmbient = packedAmbient >> 20 & 0xF;
|
||||
int blockLightAmbient = packedAmbient >> 4 & 0xF;
|
||||
int skyLightCurrent = (int)Mth.m_14179_((float)progress, (float)15.0f, (float)skyLightAmbient);
|
||||
int blockLightCurrent = (int)Mth.m_14179_((float)progress, (float)15.0f, (float)blockLightAmbient);
|
||||
return skyLightCurrent << 20 | blockLightCurrent << 4;
|
||||
}
|
||||
return super.m_6355_(pPartialTick);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul.client;
|
||||
|
||||
import com.vinlanx.explosionoverhaul.CustomGlowParticleOptions;
|
||||
import com.vinlanx.explosionoverhaul.client.CustomGlowParticle;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.client.particle.Particle;
|
||||
import net.minecraft.client.particle.ParticleProvider;
|
||||
import net.minecraft.client.particle.SpriteSet;
|
||||
|
||||
public class CustomGlowParticleProvider
|
||||
implements ParticleProvider<CustomGlowParticleOptions> {
|
||||
public CustomGlowParticleProvider(SpriteSet pSprites) {
|
||||
}
|
||||
|
||||
public Particle createParticle(CustomGlowParticleOptions options, ClientLevel pLevel, double pX, double pY, double pZ, double pXSpeed, double pYSpeed, double pZSpeed) {
|
||||
return new CustomGlowParticle(pLevel, pX, pY, pZ, pXSpeed, pYSpeed, pZSpeed, options);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,178 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul.client;
|
||||
|
||||
import com.vinlanx.explosionoverhaul.Config;
|
||||
import com.vinlanx.explosionoverhaul.client.LowPassConcussionEffect;
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.Options;
|
||||
import net.minecraft.client.player.LocalPlayer;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.sounds.SoundSource;
|
||||
import net.neoforged.api.distmarker.Dist;
|
||||
import net.neoforged.api.distmarker.OnlyIn;
|
||||
import net.neoforged.neoforge.event.TickEvent;
|
||||
import net.neoforged.bus.api.SubscribeEvent;
|
||||
import net.neoforged.fml.common.Mod;
|
||||
import net.neoforged.fml.loading.FMLEnvironment;
|
||||
|
||||
@OnlyIn(value=Dist.CLIENT)
|
||||
@Mod.EventBusSubscriber(modid="explosionoverhaul", value={Dist.CLIENT})
|
||||
public class DeafnessConcussionEffect {
|
||||
public static int DELAY_TICKS = 3;
|
||||
public static int FADE_TO_SILENT_TICKS = 5;
|
||||
public static int FADE_FROM_SILENT_TICKS = 100;
|
||||
private static Phase phase = Phase.NONE;
|
||||
private static int ticksInPhase = 0;
|
||||
private static int phaseTicksTotal = 0;
|
||||
private static int silentTicks = 0;
|
||||
private static double baseMasterVolume = 1.0;
|
||||
private static float currentIntensity = 0.0f;
|
||||
private static float lastIntensity = 0.0f;
|
||||
public static boolean debugShowChat = false;
|
||||
public static volatile boolean enabled = true;
|
||||
|
||||
public static boolean start(float intensity, double silentSeconds, double effectivePercent, String visibility, int intensityPercent) {
|
||||
LocalPlayer player;
|
||||
float effectiveIntensity;
|
||||
if (!FMLEnvironment.dist.isClient()) {
|
||||
return false;
|
||||
}
|
||||
if (!enabled) {
|
||||
return false;
|
||||
}
|
||||
float f = effectiveIntensity = (Boolean)Config.CLIENT.enableDeafness.get() != false ? intensity : 0.001f;
|
||||
if (effectiveIntensity < 1.0E-4f) {
|
||||
return false;
|
||||
}
|
||||
Minecraft mc = Minecraft.m_91087_();
|
||||
if (mc == null || mc.f_91073_ == null || mc.f_91074_ == null) {
|
||||
return false;
|
||||
}
|
||||
Options options = mc.f_91066_;
|
||||
if (options == null) {
|
||||
return false;
|
||||
}
|
||||
baseMasterVolume = (Double)options.m_246669_(SoundSource.MASTER).m_231551_();
|
||||
if (phase != Phase.NONE) {
|
||||
currentIntensity = Math.min(1.0f, currentIntensity + effectiveIntensity);
|
||||
silentTicks = Math.min(2000, silentTicks + (int)Math.round(silentSeconds * 20.0));
|
||||
if (phase != Phase.SILENT) {
|
||||
phase = Phase.FADE_IN;
|
||||
ticksInPhase = 0;
|
||||
phaseTicksTotal = FADE_TO_SILENT_TICKS;
|
||||
}
|
||||
} else {
|
||||
currentIntensity = effectiveIntensity;
|
||||
silentTicks = Math.max(0, (int)Math.round(silentSeconds * 20.0));
|
||||
phase = Phase.DELAY;
|
||||
ticksInPhase = 0;
|
||||
phaseTicksTotal = DELAY_TICKS;
|
||||
}
|
||||
lastIntensity = currentIntensity;
|
||||
if (debugShowChat && (player = mc.f_91074_) != null) {
|
||||
String msg = String.format("\u041f\u043e\u0442\u0443\u0436\u043d\u0456\u0441\u0442\u044c \u043a\u043e\u043d\u0442\u0443\u0437\u0456\u0457 %.1f%% (%s) \u2014 \u0421\u0438\u043b\u0430 \u0441\u043a\u0440\u0443\u0447\u0443\u0432\u0430\u043d\u043d\u044f %d%%, \u0427\u0430\u0441 \u0441\u043a\u0440\u0443\u0447\u0443\u0432\u0430\u043d\u043d\u044f %.1f \u0441\u0435\u043a", effectivePercent, visibility, intensityPercent, silentSeconds);
|
||||
player.m_5661_((Component)Component.m_237113_((String)msg).m_130940_(ChatFormatting.WHITE), false);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onClientTick(TickEvent.ClientTickEvent event) {
|
||||
if (event.phase != TickEvent.Phase.END) {
|
||||
return;
|
||||
}
|
||||
if (phase == Phase.NONE) {
|
||||
return;
|
||||
}
|
||||
Minecraft mc = Minecraft.m_91087_();
|
||||
if (mc == null || mc.f_91066_ == null) {
|
||||
DeafnessConcussionEffect.resetVolume();
|
||||
return;
|
||||
}
|
||||
if (mc.m_91104_()) {
|
||||
return;
|
||||
}
|
||||
double t = Math.min(1.0, (double)(++ticksInPhase) / (double)phaseTicksTotal);
|
||||
switch (phase) {
|
||||
case DELAY: {
|
||||
if (ticksInPhase < phaseTicksTotal) break;
|
||||
DeafnessConcussionEffect.nextPhase(Phase.FADE_IN, FADE_TO_SILENT_TICKS);
|
||||
break;
|
||||
}
|
||||
case FADE_IN: {
|
||||
double minGain = baseMasterVolume * (1.0 - (double)currentIntensity);
|
||||
double gain = DeafnessConcussionEffect.lerp(baseMasterVolume, minGain, DeafnessConcussionEffect.easeOutQuad(t));
|
||||
DeafnessConcussionEffect.applyMasterVolume(mc, gain);
|
||||
if (ticksInPhase < phaseTicksTotal) break;
|
||||
DeafnessConcussionEffect.nextPhase(Phase.SILENT, silentTicks);
|
||||
break;
|
||||
}
|
||||
case SILENT: {
|
||||
double minGain = baseMasterVolume * (1.0 - (double)currentIntensity);
|
||||
DeafnessConcussionEffect.applyMasterVolume(mc, minGain);
|
||||
if (ticksInPhase < phaseTicksTotal) break;
|
||||
DeafnessConcussionEffect.nextPhase(Phase.FADE_OUT, FADE_FROM_SILENT_TICKS);
|
||||
break;
|
||||
}
|
||||
case FADE_OUT: {
|
||||
double minGain = baseMasterVolume * (1.0 - (double)currentIntensity);
|
||||
double gain = DeafnessConcussionEffect.lerp(minGain, baseMasterVolume, DeafnessConcussionEffect.easeInOutQuad(t));
|
||||
DeafnessConcussionEffect.applyMasterVolume(mc, gain);
|
||||
if (ticksInPhase < phaseTicksTotal) break;
|
||||
DeafnessConcussionEffect.stop();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void nextPhase(Phase next, int durationTicks) {
|
||||
phase = next;
|
||||
ticksInPhase = 0;
|
||||
phaseTicksTotal = durationTicks;
|
||||
}
|
||||
|
||||
public static void stop() {
|
||||
DeafnessConcussionEffect.resetVolume();
|
||||
phase = Phase.NONE;
|
||||
ticksInPhase = 0;
|
||||
phaseTicksTotal = 0;
|
||||
lastIntensity = 0.0f;
|
||||
}
|
||||
|
||||
public static boolean isActive() {
|
||||
return phase != Phase.NONE;
|
||||
}
|
||||
|
||||
private static void resetVolume() {
|
||||
LowPassConcussionEffect.setDeafnessGain(1.0f);
|
||||
}
|
||||
|
||||
private static void applyMasterVolume(Minecraft mc, double volume) {
|
||||
float clamped = (float)Math.max(0.0, Math.min(1.0, volume));
|
||||
LowPassConcussionEffect.setDeafnessGain(clamped);
|
||||
}
|
||||
|
||||
private static double lerp(double a, double b, double t) {
|
||||
return a + (b - a) * t;
|
||||
}
|
||||
|
||||
private static double easeOutQuad(double t) {
|
||||
return 1.0 - (1.0 - t) * (1.0 - t);
|
||||
}
|
||||
|
||||
private static double easeInOutQuad(double t) {
|
||||
return t < 0.5 ? 2.0 * t * t : 1.0 - Math.pow(-2.0 * t + 2.0, 2.0) / 2.0;
|
||||
}
|
||||
|
||||
private static enum Phase {
|
||||
NONE,
|
||||
DELAY,
|
||||
FADE_IN,
|
||||
SILENT,
|
||||
FADE_OUT;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul.client;
|
||||
|
||||
import com.mojang.blaze3d.platform.NativeImage;
|
||||
import com.mojang.logging.LogUtils;
|
||||
import com.vinlanx.explosionoverhaul.Config;
|
||||
import com.vinlanx.explosionoverhaul.ExplosionOverhaul;
|
||||
import java.io.InputStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.texture.DynamicTexture;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.packs.resources.Resource;
|
||||
|
||||
public class ExplosionTextureManager {
|
||||
private static final LogUtils LOGGER_WRAPPER = null;
|
||||
private static final ExplosionTextureManager INSTANCE = new ExplosionTextureManager();
|
||||
private final Map<Integer, DynamicTexture> textures = new HashMap<Integer, DynamicTexture>();
|
||||
private final Map<Integer, ResourceLocation> resourceLocations = new HashMap<Integer, ResourceLocation>();
|
||||
public static final int INDEX_SOFT_GLOW = 0;
|
||||
public static final int INDEX_SOFT_GLOW_E = 1;
|
||||
public static final int GLOW_BASE_START = 2;
|
||||
public static final int GLOW_EMISSIVE_START = 6;
|
||||
public static final int GLOW2_BASE_START = 10;
|
||||
public static final int GLOW2_EMISSIVE_START = 14;
|
||||
public static final int SGLOW_BASE_START = 18;
|
||||
public static final int SGLOW_EMISSIVE_START = 22;
|
||||
private static final String BASE_PATH = "explosions/";
|
||||
|
||||
public static ExplosionTextureManager getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
private ExplosionTextureManager() {
|
||||
}
|
||||
|
||||
public void reload() {
|
||||
this.clear();
|
||||
if (Minecraft.m_91087_().m_91098_() == null) {
|
||||
return;
|
||||
}
|
||||
ExplosionOverhaul.LOGGER.info("Reloading Explosion Texture Manager...");
|
||||
this.loadTexture(0, "soft_glow.png");
|
||||
this.loadTexture(1, "soft_glow_e.png");
|
||||
Config.Client.ParticleRenderMode mode = (Config.Client.ParticleRenderMode)((Object)Config.CLIENT.particleRenderMode.get());
|
||||
if (mode == Config.Client.ParticleRenderMode.VANILA) {
|
||||
ExplosionOverhaul.LOGGER.info("Vanilla mode active - skipping high-res sheet loading to save VRAM.");
|
||||
return;
|
||||
}
|
||||
Config.Client.GlowTextureQuality quality = (Config.Client.GlowTextureQuality)((Object)Config.CLIENT.glowTextureQuality.get());
|
||||
boolean is64 = quality == Config.Client.GlowTextureQuality.QUALITY_64;
|
||||
this.loadSheetGroup(2, "glow/glow_sheet_", is64);
|
||||
this.loadSheetGroup(6, "glow/glow_e_sheet_", is64);
|
||||
this.loadSheetGroup(10, "glow_2/glow_2_sheet_", is64);
|
||||
this.loadSheetGroup(14, "glow_2/glow_2_e_sheet_", is64);
|
||||
this.loadSheetGroup(18, "sglow/sglow_sheet_", is64);
|
||||
this.loadSheetGroup(22, "sglow/sglow_e_sheet_", is64);
|
||||
ExplosionOverhaul.LOGGER.info("Explosion sheets loaded successfully (Quality: {}).", (Object)(is64 ? "64" : "256"));
|
||||
}
|
||||
|
||||
private void loadSheetGroup(int startIndex, String prefix, boolean is64) {
|
||||
String pathPrefix = is64 ? prefix.replace("/", "/64/") : prefix;
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
this.loadTexture(startIndex + i, pathPrefix + (i + 1) + ".png");
|
||||
}
|
||||
}
|
||||
|
||||
private void loadTexture(int index, String path) {
|
||||
ResourceLocation fullPath = new ResourceLocation("explosionoverhaul", BASE_PATH + path);
|
||||
try {
|
||||
InputStream is = ((Resource)Minecraft.m_91087_().m_91098_().m_213713_(fullPath).get()).m_215507_();
|
||||
NativeImage image = NativeImage.m_85058_((InputStream)is);
|
||||
DynamicTexture texture = new DynamicTexture(image);
|
||||
ResourceLocation loc = Minecraft.m_91087_().m_91097_().m_118490_("explosion_sheet_" + index, texture);
|
||||
this.textures.put(index, texture);
|
||||
this.resourceLocations.put(index, loc);
|
||||
}
|
||||
catch (Exception e) {
|
||||
ExplosionOverhaul.LOGGER.error("Failed to load explosion sheet from {}: {}", (Object)fullPath, (Object)e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public ResourceLocation getTexture(int index) {
|
||||
ResourceLocation loc = this.resourceLocations.get(index);
|
||||
if (loc == null) {
|
||||
loc = this.resourceLocations.get(0);
|
||||
}
|
||||
if (loc == null) {
|
||||
return new ResourceLocation("minecraft", "textures/particle/generic_0.png");
|
||||
}
|
||||
return loc;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
this.textures.values().forEach(DynamicTexture::close);
|
||||
this.textures.clear();
|
||||
this.resourceLocations.clear();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul.client;
|
||||
|
||||
import com.vinlanx.explosionoverhaul.Config;
|
||||
import java.util.Random;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
public class ExplosionWindController {
|
||||
private static final double BASE_SPEED = 0.05;
|
||||
private static final double MAX_SPEED = 0.06;
|
||||
private static final double LERP_FACTOR = 0.03;
|
||||
private static final Random RANDOM = new Random();
|
||||
private static final double[] HEIGHT_STOPS = new double[]{0.0, 0.25, 0.5, 0.75, 1.0};
|
||||
private static final double[] DUST_SPEEDS = new double[]{0.02, 0.02, 0.02, 0.02, 0.02};
|
||||
private static final double[] GLOW_SPEEDS = new double[]{0.0, 0.02, 0.04, 0.06, 0.08};
|
||||
private static Vec3 currentWind = Vec3.f_82478_;
|
||||
private static Vec3 targetDirection = Vec3.f_82478_;
|
||||
private static int ticksUntilDirectionShift = 0;
|
||||
|
||||
private ExplosionWindController() {
|
||||
}
|
||||
|
||||
public static void tick() {
|
||||
Vec3 desiredWind;
|
||||
if (ticksUntilDirectionShift-- <= 0) {
|
||||
targetDirection = ExplosionWindController.randomHorizontalDirection();
|
||||
ticksUntilDirectionShift = 80 + RANDOM.nextInt(120);
|
||||
}
|
||||
if ((currentWind = ExplosionWindController.lerp(currentWind, desiredWind = targetDirection.m_82490_(0.05), 0.03)).m_82553_() > 0.06) {
|
||||
currentWind = currentWind.m_82541_().m_82490_(0.06);
|
||||
}
|
||||
}
|
||||
|
||||
public static void reset() {
|
||||
currentWind = Vec3.f_82478_;
|
||||
targetDirection = Vec3.f_82478_;
|
||||
ticksUntilDirectionShift = 0;
|
||||
}
|
||||
|
||||
public static Vec3 getWind() {
|
||||
if (!((Boolean)Config.CLIENT.enableWindEffect.get()).booleanValue()) {
|
||||
return Vec3.f_82478_;
|
||||
}
|
||||
double multiplier = (Double)Config.CLIENT.windSpeedMultiplier.get();
|
||||
return currentWind.m_82490_(multiplier);
|
||||
}
|
||||
|
||||
public static Vec3 getScaledWind(double scale) {
|
||||
if (!((Boolean)Config.CLIENT.enableWindEffect.get()).booleanValue()) {
|
||||
return Vec3.f_82478_;
|
||||
}
|
||||
double multiplier = (Double)Config.CLIENT.windSpeedMultiplier.get();
|
||||
return currentWind.m_82490_(scale * multiplier);
|
||||
}
|
||||
|
||||
public static Vec3 getWindDirection() {
|
||||
if (!((Boolean)Config.CLIENT.enableWindEffect.get()).booleanValue()) {
|
||||
return Vec3.f_82478_;
|
||||
}
|
||||
double length = Math.sqrt(ExplosionWindController.currentWind.f_82479_ * ExplosionWindController.currentWind.f_82479_ + ExplosionWindController.currentWind.f_82481_ * ExplosionWindController.currentWind.f_82481_);
|
||||
if (length < 1.0E-4) {
|
||||
return Vec3.f_82478_;
|
||||
}
|
||||
return new Vec3(ExplosionWindController.currentWind.f_82479_ / length, 0.0, ExplosionWindController.currentWind.f_82481_ / length);
|
||||
}
|
||||
|
||||
private static double getWeatherMultiplier() {
|
||||
Minecraft minecraft = Minecraft.m_91087_();
|
||||
if (minecraft.f_91073_ != null && minecraft.f_91074_ != null) {
|
||||
Biome.Precipitation precipitation = ((Biome)minecraft.f_91073_.m_204166_(minecraft.f_91074_.m_20183_()).m_203334_()).m_264600_(minecraft.f_91074_.m_20183_());
|
||||
if (minecraft.f_91073_.m_46471_() || minecraft.f_91073_.m_46470_()) {
|
||||
return 1.5;
|
||||
}
|
||||
}
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
public static double computeDustSpeed(double heightPercent) {
|
||||
if (!((Boolean)Config.CLIENT.enableWindEffect.get()).booleanValue()) {
|
||||
return 0.0;
|
||||
}
|
||||
double baseSpeed = ExplosionWindController.sampleProfile(heightPercent, DUST_SPEEDS);
|
||||
double weatherMultiplier = ExplosionWindController.getWeatherMultiplier();
|
||||
return baseSpeed * (Double)Config.CLIENT.windSpeedMultiplier.get() * weatherMultiplier;
|
||||
}
|
||||
|
||||
public static double computeGlowSpeed(double heightPercent) {
|
||||
if (!((Boolean)Config.CLIENT.enableWindEffect.get()).booleanValue()) {
|
||||
return 0.0;
|
||||
}
|
||||
double baseSpeed = ExplosionWindController.sampleProfile(heightPercent, GLOW_SPEEDS);
|
||||
double weatherMultiplier = ExplosionWindController.getWeatherMultiplier();
|
||||
return baseSpeed * (Double)Config.CLIENT.windSpeedMultiplier.get() * weatherMultiplier;
|
||||
}
|
||||
|
||||
public static Vec3 getDustWindVector(double heightPercent) {
|
||||
Vec3 direction = ExplosionWindController.getWindDirection();
|
||||
if (direction == Vec3.f_82478_) {
|
||||
return direction;
|
||||
}
|
||||
return direction.m_82490_(ExplosionWindController.computeDustSpeed(heightPercent));
|
||||
}
|
||||
|
||||
public static Vec3 getGlowWindVector(double heightPercent) {
|
||||
Vec3 direction = ExplosionWindController.getWindDirection();
|
||||
if (direction == Vec3.f_82478_) {
|
||||
return direction;
|
||||
}
|
||||
return direction.m_82490_(ExplosionWindController.computeGlowSpeed(heightPercent));
|
||||
}
|
||||
|
||||
private static double sampleProfile(double heightPercent, double[] speeds) {
|
||||
double clamped = Math.max(0.0, Math.min(1.0, heightPercent));
|
||||
for (int i = 1; i < HEIGHT_STOPS.length; ++i) {
|
||||
double prevStop = HEIGHT_STOPS[i - 1];
|
||||
double stop = HEIGHT_STOPS[i];
|
||||
if (!(clamped <= stop)) continue;
|
||||
double t = stop <= prevStop ? 0.0 : (clamped - prevStop) / (stop - prevStop);
|
||||
double prevValue = speeds[i - 1];
|
||||
double value = speeds[i];
|
||||
return prevValue + (value - prevValue) * t;
|
||||
}
|
||||
return speeds[speeds.length - 1];
|
||||
}
|
||||
|
||||
private static Vec3 lerp(Vec3 from, Vec3 to, double factor) {
|
||||
double clamped = Math.max(0.0, Math.min(1.0, factor));
|
||||
double x = from.f_82479_ + (to.f_82479_ - from.f_82479_) * clamped;
|
||||
double y = from.f_82480_ + (to.f_82480_ - from.f_82480_) * clamped;
|
||||
double z = from.f_82481_ + (to.f_82481_ - from.f_82481_) * clamped;
|
||||
return new Vec3(x, y, z);
|
||||
}
|
||||
|
||||
private static Vec3 randomHorizontalDirection() {
|
||||
double angle = RANDOM.nextDouble() * Math.PI * 2.0;
|
||||
double x = Math.cos(angle);
|
||||
double z = Math.sin(angle);
|
||||
return new Vec3(x, 0.0, z);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul.client;
|
||||
|
||||
import net.minecraft.client.resources.sounds.AbstractTickableSoundInstance;
|
||||
import net.minecraft.client.resources.sounds.SoundInstance;
|
||||
import net.minecraft.sounds.SoundEvent;
|
||||
import net.minecraft.sounds.SoundSource;
|
||||
import net.minecraft.util.RandomSource;
|
||||
|
||||
public class FadingMusicInstance
|
||||
extends AbstractTickableSoundInstance {
|
||||
private float targetVolume = 1.0f;
|
||||
private float fadeSpeed = 0.0f;
|
||||
private boolean shouldStop = false;
|
||||
|
||||
public FadingMusicInstance(SoundEvent sound, float volume, SoundSource source) {
|
||||
super(sound, source, RandomSource.m_216327_());
|
||||
this.f_119578_ = true;
|
||||
this.f_119579_ = 0;
|
||||
this.f_119573_ = volume;
|
||||
this.f_119574_ = 1.0f;
|
||||
this.f_119575_ = 0.0;
|
||||
this.f_119576_ = 0.0;
|
||||
this.f_119577_ = 0.0;
|
||||
this.f_119582_ = true;
|
||||
this.f_119580_ = SoundInstance.Attenuation.NONE;
|
||||
this.targetVolume = volume;
|
||||
}
|
||||
|
||||
public void m_7788_() {
|
||||
if (Math.abs(this.f_119573_ - this.targetVolume) > 0.001f) {
|
||||
if (this.fadeSpeed != 0.0f) {
|
||||
this.f_119573_ += this.fadeSpeed;
|
||||
if (this.fadeSpeed > 0.0f && this.f_119573_ >= this.targetVolume) {
|
||||
this.f_119573_ = this.targetVolume;
|
||||
} else if (this.fadeSpeed < 0.0f && this.f_119573_ <= this.targetVolume) {
|
||||
this.f_119573_ = this.targetVolume;
|
||||
}
|
||||
this.f_119573_ = Math.max(0.0f, Math.min(1.0f, this.f_119573_));
|
||||
} else {
|
||||
this.f_119573_ = this.targetVolume;
|
||||
}
|
||||
}
|
||||
if (this.shouldStop && this.f_119573_ <= 0.001f) {
|
||||
this.m_119609_();
|
||||
}
|
||||
}
|
||||
|
||||
public void fadeTo(float targetVolume, float durationSeconds) {
|
||||
this.targetVolume = Math.max(0.0f, Math.min(1.0f, targetVolume));
|
||||
float totalTicks = durationSeconds * 20.0f;
|
||||
float volumeDifference = this.targetVolume - this.f_119573_;
|
||||
this.fadeSpeed = volumeDifference / totalTicks;
|
||||
}
|
||||
|
||||
public void fadeOutAndStop(float durationSeconds) {
|
||||
this.fadeTo(0.0f, durationSeconds);
|
||||
this.shouldStop = true;
|
||||
}
|
||||
|
||||
public float getCurrentVolume() {
|
||||
return this.f_119573_;
|
||||
}
|
||||
|
||||
public boolean hasFinishedFading() {
|
||||
return this.shouldStop && this.f_119573_ <= 0.001f;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,751 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul.client;
|
||||
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.vinlanx.explosionoverhaul.Config;
|
||||
import com.vinlanx.explosionoverhaul.ExplosionOverhaul;
|
||||
import com.vinlanx.explosionoverhaul.ModSounds;
|
||||
import com.vinlanx.explosionoverhaul.client.BackgroundParticle;
|
||||
import com.vinlanx.explosionoverhaul.client.ExplosionTextureManager;
|
||||
import com.vinlanx.explosionoverhaul.client.IntroMusicManager;
|
||||
import com.vinlanx.explosionoverhaul.client.SpriteSheetAnimator;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiGraphics;
|
||||
import net.minecraft.client.gui.screens.Screen;
|
||||
import net.minecraft.client.gui.screens.TitleScreen;
|
||||
import net.minecraft.client.resources.sounds.SimpleSoundInstance;
|
||||
import net.minecraft.client.resources.sounds.SoundInstance;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.sounds.SoundEvent;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.util.RandomSource;
|
||||
|
||||
public class FirstTimeScreen
|
||||
extends Screen {
|
||||
private static final ResourceLocation SPRITE_REALISTIC = ResourceLocation.fromNamespaceAndPath((String)"explosionoverhaul", (String)"intro_gui/gui_screen_1.png");
|
||||
private static final ResourceLocation SPRITE_VANILLA = ResourceLocation.fromNamespaceAndPath((String)"explosionoverhaul", (String)"intro_gui/gui_screen_2.png");
|
||||
private static final ResourceLocation SPRITE_REALISTIC_2 = ResourceLocation.fromNamespaceAndPath((String)"explosionoverhaul", (String)"intro_gui/gui_screen_3.png");
|
||||
private static final ResourceLocation SPRITE_STYLE_256 = ResourceLocation.fromNamespaceAndPath((String)"explosionoverhaul", (String)"intro_gui/gui_screen_1.png");
|
||||
private static final ResourceLocation SPRITE_STYLE_64 = ResourceLocation.fromNamespaceAndPath((String)"explosionoverhaul", (String)"intro_gui/gui_screen_4.png");
|
||||
private static final int FRAME_WIDTH = 854;
|
||||
private static final int FRAME_HEIGHT = 480;
|
||||
private static final int COLUMNS = 10;
|
||||
private static final int ROWS = 10;
|
||||
private static final int TOTAL_FRAMES = 61;
|
||||
private static final int FPS = 15;
|
||||
private static final int COLOR_BG = -15921907;
|
||||
private static final int COLOR_ACCENT_ORANGE = -881908;
|
||||
private static final int COLOR_ACCENT_RED = -4250588;
|
||||
private static final int COLOR_ACCENT_ROSE = -2529701;
|
||||
private static final int COLOR_ACCENT_DARK_RED = -10939115;
|
||||
private ScreenState currentState = ScreenState.CHOOSING_MODE;
|
||||
private Config.Client.ParticleRenderMode selectedRenderMode = null;
|
||||
private SpriteSheetAnimator realisticAnimator;
|
||||
private SpriteSheetAnimator vanillaAnimator;
|
||||
private SpriteSheetAnimator realistic2Animator;
|
||||
private SpriteSheetAnimator style256Animator;
|
||||
private SpriteSheetAnimator style64Animator;
|
||||
private boolean shouldSwitchState = false;
|
||||
private ScreenState nextState = ScreenState.CHOOSING_MODE;
|
||||
private int leftBoxX;
|
||||
private int leftBoxY;
|
||||
private int leftBoxW;
|
||||
private int leftBoxH;
|
||||
private int rightBoxX;
|
||||
private int rightBoxY;
|
||||
private int rightBoxW;
|
||||
private int rightBoxH;
|
||||
private int bottomBoxX;
|
||||
private int bottomBoxY;
|
||||
private int bottomBoxW;
|
||||
private int bottomBoxH;
|
||||
private int backButtonX;
|
||||
private int backButtonY;
|
||||
private int backButtonW;
|
||||
private int backButtonH;
|
||||
private boolean backButtonHovered = false;
|
||||
private float backButtonScale = 1.0f;
|
||||
private float leftHoverScale = 1.0f;
|
||||
private float rightHoverScale = 1.0f;
|
||||
private float bottomHoverScale = 1.0f;
|
||||
private static final float HOVER_SCALE_TARGET = 1.05f;
|
||||
private static final float SCALE_SPEED = 0.15f;
|
||||
private boolean leftHovered = false;
|
||||
private boolean rightHovered = false;
|
||||
private boolean bottomHovered = false;
|
||||
private long lastFrameTime = System.currentTimeMillis();
|
||||
private float transitionAlpha = 1.0f;
|
||||
private boolean isTransitioning = false;
|
||||
private static final float TRANSITION_DURATION = 0.8f;
|
||||
private float transitionTime = 0.0f;
|
||||
private List<BackgroundParticle> particles = new ArrayList<BackgroundParticle>();
|
||||
private RandomSource random = RandomSource.m_216327_();
|
||||
private float backgroundTime = 0.0f;
|
||||
private IntroMusicManager musicManager;
|
||||
private static final float FADE_IN_DURATION = 5.0f;
|
||||
private static final float FADE_OUT_DURATION = 3.0f;
|
||||
private float fadeTime = 0.0f;
|
||||
private boolean fadingIn = true;
|
||||
private boolean fadingOut = false;
|
||||
private float screenAlpha = 0.0f;
|
||||
private float fadeOutStartAlpha = 1.0f;
|
||||
private long fadeOutStartMillis = -1L;
|
||||
private static final long FORCE_CLOSE_BUFFER_MS = 2000L;
|
||||
|
||||
public FirstTimeScreen() {
|
||||
super((Component)Component.m_237113_((String)"First Time Setup"));
|
||||
}
|
||||
|
||||
protected void m_7856_() {
|
||||
int i;
|
||||
int displayHeight;
|
||||
int displayWidth;
|
||||
super.m_7856_();
|
||||
this.fadingIn = true;
|
||||
this.fadingOut = false;
|
||||
this.fadeTime = 0.0f;
|
||||
this.screenAlpha = 0.0f;
|
||||
this.lastFrameTime = System.currentTimeMillis();
|
||||
this.leftHovered = false;
|
||||
this.rightHovered = false;
|
||||
this.bottomHovered = false;
|
||||
this.backButtonHovered = false;
|
||||
this.backButtonScale = 1.0f;
|
||||
this.musicManager = IntroMusicManager.getInstance();
|
||||
if (this.currentState == ScreenState.CHOOSING_MODE) {
|
||||
this.realisticAnimator = new SpriteSheetAnimator(SPRITE_REALISTIC, 854, 480, 10, 10, 61, 15);
|
||||
this.vanillaAnimator = new SpriteSheetAnimator(SPRITE_VANILLA, 854, 480, 10, 10, 61, 15);
|
||||
this.realistic2Animator = new SpriteSheetAnimator(SPRITE_REALISTIC_2, 854, 480, 10, 10, 61, 15);
|
||||
this.realisticAnimator.load();
|
||||
this.vanillaAnimator.load();
|
||||
this.realistic2Animator.load();
|
||||
} else if (this.currentState == ScreenState.CHOOSING_STYLE) {
|
||||
this.style256Animator = new SpriteSheetAnimator(SPRITE_STYLE_256, 854, 480, 10, 10, 61, 15);
|
||||
this.style64Animator = new SpriteSheetAnimator(SPRITE_STYLE_64, 854, 480, 10, 10, 61, 15);
|
||||
this.style256Animator.load();
|
||||
this.style64Animator.load();
|
||||
ExplosionOverhaul.LOGGER.warn("Style selection screen loaded. Ensure gui_screen_4.png and gui_screen_5.png exist in intro_gui folder for proper animations.");
|
||||
}
|
||||
int maxWidth = (int)((float)this.f_96543_ * 0.3f);
|
||||
int maxHeight = (int)((float)this.f_96544_ * 0.44f);
|
||||
float aspectRatio = 1.7777778f;
|
||||
if ((float)maxWidth / aspectRatio <= (float)maxHeight) {
|
||||
displayWidth = maxWidth;
|
||||
displayHeight = (int)((float)maxWidth / aspectRatio);
|
||||
} else {
|
||||
displayHeight = maxHeight;
|
||||
displayWidth = (int)((float)maxHeight * aspectRatio);
|
||||
}
|
||||
if (this.currentState == ScreenState.CHOOSING_MODE) {
|
||||
gap = (int)((float)this.f_96543_ * 0.03f);
|
||||
totalWidth = displayWidth * 2 + gap;
|
||||
startX = (this.f_96543_ - totalWidth) / 2;
|
||||
startY = (this.f_96544_ - displayHeight) / 2 - (int)((float)this.f_96544_ * 0.15f);
|
||||
this.leftBoxX = startX;
|
||||
this.leftBoxY = startY;
|
||||
this.leftBoxW = displayWidth;
|
||||
this.leftBoxH = displayHeight;
|
||||
this.rightBoxX = startX + displayWidth + gap;
|
||||
this.rightBoxY = startY;
|
||||
this.rightBoxW = displayWidth;
|
||||
this.rightBoxH = displayHeight;
|
||||
this.bottomBoxX = (this.f_96543_ - displayWidth) / 2;
|
||||
this.bottomBoxY = startY + displayHeight + (int)((float)this.f_96544_ * 0.08f);
|
||||
this.bottomBoxW = displayWidth;
|
||||
this.bottomBoxH = displayHeight;
|
||||
} else if (this.currentState == ScreenState.CHOOSING_STYLE) {
|
||||
gap = (int)((float)this.f_96543_ * 0.03f);
|
||||
totalWidth = displayWidth * 2 + gap;
|
||||
startX = (this.f_96543_ - totalWidth) / 2;
|
||||
startY = (this.f_96544_ - displayHeight) / 2;
|
||||
this.leftBoxX = startX;
|
||||
this.leftBoxY = startY;
|
||||
this.leftBoxW = displayWidth;
|
||||
this.leftBoxH = displayHeight;
|
||||
this.rightBoxX = startX + displayWidth + gap;
|
||||
this.rightBoxY = startY;
|
||||
this.rightBoxW = displayWidth;
|
||||
this.rightBoxH = displayHeight;
|
||||
this.bottomBoxX = 0;
|
||||
this.bottomBoxY = 0;
|
||||
this.bottomBoxW = 0;
|
||||
this.bottomBoxH = 0;
|
||||
this.backButtonW = (int)((float)this.f_96543_ * 0.1f);
|
||||
this.backButtonH = (int)((float)this.f_96544_ * 0.08f);
|
||||
this.backButtonX = (int)((float)this.f_96543_ * 0.02f);
|
||||
this.backButtonY = this.f_96544_ - this.backButtonH - (int)((float)this.f_96544_ * 0.02f);
|
||||
}
|
||||
for (i = 0; i < 40; ++i) {
|
||||
this.particles.add(BackgroundParticle.createSpark(this.random, this.f_96543_, this.f_96544_));
|
||||
}
|
||||
for (i = 0; i < 15; ++i) {
|
||||
this.particles.add(BackgroundParticle.createEmber(this.random, this.f_96543_, this.f_96544_));
|
||||
}
|
||||
for (i = 0; i < 8; ++i) {
|
||||
this.particles.add(BackgroundParticle.createSmoke(this.random, this.f_96543_, this.f_96544_));
|
||||
}
|
||||
}
|
||||
|
||||
public void m_86600_() {
|
||||
float progress;
|
||||
super.m_86600_();
|
||||
long currentTime = System.currentTimeMillis();
|
||||
float rawDeltaTime = (float)(currentTime - this.lastFrameTime) / 1000.0f;
|
||||
this.lastFrameTime = currentTime;
|
||||
float deltaTime = Math.min(rawDeltaTime, 0.1f);
|
||||
this.backgroundTime += deltaTime;
|
||||
if (this.isTransitioning) {
|
||||
this.transitionTime += deltaTime;
|
||||
progress = Math.min(1.0f, this.transitionTime / 0.8f);
|
||||
if (this.transitionTime < 0.4f) {
|
||||
this.transitionAlpha = 1.0f - progress * 2.0f;
|
||||
} else {
|
||||
this.transitionAlpha = (progress - 0.5f) * 2.0f;
|
||||
if (this.transitionTime >= 0.4f && !this.shouldSwitchState) {
|
||||
this.shouldSwitchState = true;
|
||||
if (this.currentState == ScreenState.CHOOSING_MODE) {
|
||||
if (this.realisticAnimator != null) {
|
||||
this.realisticAnimator.close();
|
||||
}
|
||||
if (this.vanillaAnimator != null) {
|
||||
this.vanillaAnimator.close();
|
||||
}
|
||||
if (this.realistic2Animator != null) {
|
||||
this.realistic2Animator.close();
|
||||
}
|
||||
this.nextState = ScreenState.CHOOSING_STYLE;
|
||||
} else if (this.currentState == ScreenState.CHOOSING_STYLE) {
|
||||
if (this.style256Animator != null) {
|
||||
this.style256Animator.close();
|
||||
}
|
||||
if (this.style64Animator != null) {
|
||||
this.style64Animator.close();
|
||||
}
|
||||
this.nextState = ScreenState.CHOOSING_MODE;
|
||||
}
|
||||
this.currentState = this.nextState;
|
||||
this.m_7856_();
|
||||
}
|
||||
}
|
||||
if (this.transitionTime >= 0.8f) {
|
||||
this.isTransitioning = false;
|
||||
this.transitionAlpha = 1.0f;
|
||||
this.transitionTime = 0.0f;
|
||||
this.shouldSwitchState = false;
|
||||
}
|
||||
}
|
||||
if (this.fadingIn) {
|
||||
this.fadeTime += deltaTime;
|
||||
progress = Math.min(1.0f, this.fadeTime / 5.0f);
|
||||
this.screenAlpha = this.easeOutCubic(progress);
|
||||
if (this.fadeTime >= 5.0f) {
|
||||
this.fadingIn = false;
|
||||
this.screenAlpha = 1.0f;
|
||||
}
|
||||
} else if (this.fadingOut) {
|
||||
long threshold;
|
||||
long elapsed;
|
||||
this.fadeTime += deltaTime;
|
||||
progress = Math.min(1.0f, this.fadeTime / 3.0f);
|
||||
this.screenAlpha = this.fadeOutStartAlpha * (1.0f - this.easeInCubic(progress));
|
||||
if (this.fadeTime >= 3.0f) {
|
||||
boolean musicStillFading;
|
||||
boolean bl = musicStillFading = this.musicManager != null && this.musicManager.isFadingOut();
|
||||
if (!musicStillFading) {
|
||||
ExplosionOverhaul.LOGGER.info("Screen and music fade out complete. Opening TitleScreen.");
|
||||
this.cleanupAnimators();
|
||||
Minecraft.m_91087_().m_91152_((Screen)new TitleScreen());
|
||||
} else {
|
||||
ExplosionOverhaul.LOGGER.info("Waiting for music to finish fading...");
|
||||
}
|
||||
}
|
||||
if (this.fadeOutStartMillis > 0L && (elapsed = System.currentTimeMillis() - this.fadeOutStartMillis) > (threshold = 5000L)) {
|
||||
ExplosionOverhaul.LOGGER.warn("Fade out timeout exceeded ({} ms). Forcing close and opening TitleScreen.", (Object)elapsed);
|
||||
if (this.musicManager != null) {
|
||||
this.musicManager.stop();
|
||||
}
|
||||
this.cleanupAnimators();
|
||||
this.fadingOut = false;
|
||||
this.fadeOutStartMillis = -1L;
|
||||
Minecraft.m_91087_().m_91152_((Screen)new TitleScreen());
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (this.musicManager != null) {
|
||||
this.musicManager.tick(deltaTime);
|
||||
}
|
||||
if (this.currentState == ScreenState.CHOOSING_MODE) {
|
||||
if (this.realisticAnimator != null) {
|
||||
this.realisticAnimator.tick(deltaTime);
|
||||
}
|
||||
if (this.vanillaAnimator != null) {
|
||||
this.vanillaAnimator.tick(deltaTime);
|
||||
}
|
||||
if (this.realistic2Animator != null) {
|
||||
this.realistic2Animator.tick(deltaTime);
|
||||
}
|
||||
} else if (this.currentState == ScreenState.CHOOSING_STYLE) {
|
||||
if (this.style256Animator != null) {
|
||||
this.style256Animator.tick(deltaTime);
|
||||
}
|
||||
if (this.style64Animator != null) {
|
||||
this.style64Animator.tick(deltaTime);
|
||||
}
|
||||
}
|
||||
this.leftHoverScale = Mth.m_14179_((float)0.15f, (float)this.leftHoverScale, (float)(this.leftHovered ? 1.05f : 1.0f));
|
||||
this.rightHoverScale = Mth.m_14179_((float)0.15f, (float)this.rightHoverScale, (float)(this.rightHovered ? 1.05f : 1.0f));
|
||||
this.bottomHoverScale = Mth.m_14179_((float)0.15f, (float)this.bottomHoverScale, (float)(this.bottomHovered ? 1.05f : 1.0f));
|
||||
this.particles.removeIf(p -> {
|
||||
p.tick(deltaTime);
|
||||
return p.isDead() || p.x < -50.0f || p.x > (float)(this.f_96543_ + 50) || p.y < -50.0f || p.y > (float)(this.f_96544_ + 50);
|
||||
});
|
||||
if (this.random.m_188501_() < 0.15f) {
|
||||
this.particles.add(BackgroundParticle.createSpark(this.random, this.f_96543_, this.f_96544_));
|
||||
}
|
||||
if (this.random.m_188501_() < 0.05f) {
|
||||
this.particles.add(BackgroundParticle.createEmber(this.random, this.f_96543_, this.f_96544_));
|
||||
}
|
||||
if (this.random.m_188501_() < 0.02f) {
|
||||
this.particles.add(BackgroundParticle.createSmoke(this.random, this.f_96543_, this.f_96544_));
|
||||
}
|
||||
if (this.random.m_188501_() < 0.01f) {
|
||||
this.particles.add(BackgroundParticle.createFlash(this.random, this.f_96543_, this.f_96544_));
|
||||
}
|
||||
}
|
||||
|
||||
private void cleanupAnimators() {
|
||||
if (this.realisticAnimator != null) {
|
||||
this.realisticAnimator.close();
|
||||
}
|
||||
if (this.vanillaAnimator != null) {
|
||||
this.vanillaAnimator.close();
|
||||
}
|
||||
if (this.realistic2Animator != null) {
|
||||
this.realistic2Animator.close();
|
||||
}
|
||||
if (this.style256Animator != null) {
|
||||
this.style256Animator.close();
|
||||
}
|
||||
if (this.style64Animator != null) {
|
||||
this.style64Animator.close();
|
||||
}
|
||||
}
|
||||
|
||||
public void m_88315_(GuiGraphics graphics, int mouseX, int mouseY, float partialTick) {
|
||||
graphics.m_280509_(0, 0, this.f_96543_, this.f_96544_, -16777216);
|
||||
if (this.screenAlpha < 0.01f) {
|
||||
return;
|
||||
}
|
||||
RenderSystem.enableBlend();
|
||||
RenderSystem.defaultBlendFunc();
|
||||
float renderAlpha = this.screenAlpha * this.transitionAlpha;
|
||||
RenderSystem.setShaderColor((float)1.0f, (float)1.0f, (float)1.0f, (float)renderAlpha);
|
||||
graphics.m_280168_().m_85836_();
|
||||
this.renderCinematicBackground(graphics, partialTick, renderAlpha);
|
||||
if (this.currentState == ScreenState.CHOOSING_MODE) {
|
||||
this.renderModeSelection(graphics, mouseX, mouseY, renderAlpha);
|
||||
} else if (this.currentState == ScreenState.CHOOSING_STYLE) {
|
||||
this.renderStyleSelection(graphics, mouseX, mouseY, renderAlpha);
|
||||
}
|
||||
graphics.m_280168_().m_85849_();
|
||||
RenderSystem.setShaderColor((float)1.0f, (float)1.0f, (float)1.0f, (float)1.0f);
|
||||
super.m_88315_(graphics, mouseX, mouseY, partialTick);
|
||||
}
|
||||
|
||||
private void renderModeSelection(GuiGraphics graphics, int mouseX, int mouseY, float renderAlpha) {
|
||||
String title = "Choose Your Explosion Style";
|
||||
int titleWidth = this.f_96547_.m_92895_(title);
|
||||
int titleX = (this.f_96543_ - titleWidth) / 2;
|
||||
int titleY = this.leftBoxY - 40;
|
||||
int titleAlpha = (int)(renderAlpha * 255.0f) << 24;
|
||||
graphics.m_280056_(this.f_96547_, title, titleX + 2, titleY + 2, 0xF28B0C | (int)(64.0f * renderAlpha) << 24, false);
|
||||
graphics.m_280056_(this.f_96547_, title, titleX + 1, titleY + 1, 0xF28B0C | (int)(128.0f * renderAlpha) << 24, false);
|
||||
graphics.m_280056_(this.f_96547_, title, titleX, titleY, 0xF28B0C | titleAlpha, true);
|
||||
String subtitle = "You can change this anytime in the config";
|
||||
int subtitleWidth = this.f_96547_.m_92895_(subtitle);
|
||||
graphics.m_280056_(this.f_96547_, subtitle, (this.f_96543_ - subtitleWidth) / 2, titleY + 15, 0xCCCCCC | titleAlpha, false);
|
||||
String psNote = "P.S. Colors in the game may differ from the animations because compression has altered the colors";
|
||||
int psWidth = this.f_96547_.m_92895_(psNote);
|
||||
int psColor = 0x999999 | titleAlpha;
|
||||
graphics.m_280056_(this.f_96547_, psNote, (this.f_96543_ - psWidth) / 2, titleY + 30, psColor, false);
|
||||
if (!this.isTransitioning) {
|
||||
boolean wasLeftHovered = this.leftHovered;
|
||||
boolean wasRightHovered = this.rightHovered;
|
||||
boolean wasBottomHovered = this.bottomHovered;
|
||||
this.leftHovered = this.isMouseOver(mouseX, mouseY, this.leftBoxX, this.leftBoxY, this.leftBoxW, this.leftBoxH);
|
||||
this.rightHovered = this.isMouseOver(mouseX, mouseY, this.rightBoxX, this.rightBoxY, this.rightBoxW, this.rightBoxH);
|
||||
this.bottomHovered = this.isMouseOver(mouseX, mouseY, this.bottomBoxX, this.bottomBoxY, this.bottomBoxW, this.bottomBoxH);
|
||||
if (this.leftHovered && !wasLeftHovered) {
|
||||
this.realisticAnimator.reset();
|
||||
this.realisticAnimator.play();
|
||||
} else if (!this.leftHovered && wasLeftHovered) {
|
||||
this.realisticAnimator.reset();
|
||||
}
|
||||
if (this.rightHovered && !wasRightHovered) {
|
||||
this.vanillaAnimator.reset();
|
||||
this.vanillaAnimator.play();
|
||||
} else if (!this.rightHovered && wasRightHovered) {
|
||||
this.vanillaAnimator.reset();
|
||||
}
|
||||
if (this.bottomHovered && !wasBottomHovered) {
|
||||
this.realistic2Animator.reset();
|
||||
this.realistic2Animator.play();
|
||||
} else if (!this.bottomHovered && wasBottomHovered) {
|
||||
this.realistic2Animator.reset();
|
||||
}
|
||||
}
|
||||
this.renderBox(graphics, this.leftBoxX, this.leftBoxY, this.leftBoxW, this.leftBoxH, this.leftHoverScale, this.realisticAnimator, "REALISTIC", this.leftHovered, -881908, renderAlpha);
|
||||
this.renderBox(graphics, this.rightBoxX, this.rightBoxY, this.rightBoxW, this.rightBoxH, this.rightHoverScale, this.vanillaAnimator, "VANILLA-LIKE", this.rightHovered, -4250588, renderAlpha);
|
||||
this.renderBox(graphics, this.bottomBoxX, this.bottomBoxY, this.bottomBoxW, this.bottomBoxH, this.bottomHoverScale, this.realistic2Animator, "REALISTIC 2", this.bottomHovered, -2529701, renderAlpha);
|
||||
}
|
||||
|
||||
private void renderStyleSelection(GuiGraphics graphics, int mouseX, int mouseY, float renderAlpha) {
|
||||
String title = "Choose Render Style";
|
||||
int titleWidth = this.f_96547_.m_92895_(title);
|
||||
int titleX = (this.f_96543_ - titleWidth) / 2;
|
||||
int titleY = this.leftBoxY - 40;
|
||||
int titleAlpha = (int)(renderAlpha * 255.0f) << 24;
|
||||
graphics.m_280056_(this.f_96547_, title, titleX + 2, titleY + 2, 0xF28B0C | (int)(64.0f * renderAlpha) << 24, false);
|
||||
graphics.m_280056_(this.f_96547_, title, titleX + 1, titleY + 1, 0xF28B0C | (int)(128.0f * renderAlpha) << 24, false);
|
||||
graphics.m_280056_(this.f_96547_, title, titleX, titleY, 0xF28B0C | titleAlpha, true);
|
||||
String subtitle = "Higher quality requires more VRAM";
|
||||
int subtitleWidth = this.f_96547_.m_92895_(subtitle);
|
||||
graphics.m_280056_(this.f_96547_, subtitle, (this.f_96543_ - subtitleWidth) / 2, titleY + 15, 0xCCCCCC | titleAlpha, false);
|
||||
if (!this.isTransitioning) {
|
||||
boolean wasLeftHovered = this.leftHovered;
|
||||
boolean wasRightHovered = this.rightHovered;
|
||||
boolean wasBackHovered = this.backButtonHovered;
|
||||
this.leftHovered = this.isMouseOver(mouseX, mouseY, this.leftBoxX, this.leftBoxY, this.leftBoxW, this.leftBoxH);
|
||||
this.rightHovered = this.isMouseOver(mouseX, mouseY, this.rightBoxX, this.rightBoxY, this.rightBoxW, this.rightBoxH);
|
||||
this.backButtonHovered = this.isMouseOver(mouseX, mouseY, this.backButtonX, this.backButtonY, this.backButtonW, this.backButtonH);
|
||||
this.bottomHovered = false;
|
||||
if (this.leftHovered && !wasLeftHovered) {
|
||||
this.style256Animator.reset();
|
||||
this.style256Animator.play();
|
||||
} else if (!this.leftHovered && wasLeftHovered) {
|
||||
this.style256Animator.reset();
|
||||
}
|
||||
if (this.rightHovered && !wasRightHovered) {
|
||||
this.style64Animator.reset();
|
||||
this.style64Animator.play();
|
||||
} else if (!this.rightHovered && wasRightHovered) {
|
||||
this.style64Animator.reset();
|
||||
}
|
||||
if (this.backButtonHovered && !wasBackHovered || this.backButtonHovered || wasBackHovered) {
|
||||
// empty if block
|
||||
}
|
||||
}
|
||||
this.backButtonScale = Mth.m_14179_((float)0.15f, (float)this.backButtonScale, (float)(this.backButtonHovered ? 1.05f : 1.0f));
|
||||
this.renderBox(graphics, this.leftBoxX, this.leftBoxY, this.leftBoxW, this.leftBoxH, this.leftHoverScale, this.style256Animator, "256 PIXELS", this.leftHovered, -881908, renderAlpha);
|
||||
this.renderBox(graphics, this.rightBoxX, this.rightBoxY, this.rightBoxW, this.rightBoxH, this.rightHoverScale, this.style64Animator, "64 PIXELS", this.rightHovered, -4250588, renderAlpha);
|
||||
this.renderBackButton(graphics, renderAlpha);
|
||||
}
|
||||
|
||||
private void renderBox(GuiGraphics graphics, int x, int y, int width, int height, float scale, SpriteSheetAnimator animator, String label, boolean hovered, int accentColor, float alpha) {
|
||||
graphics.m_280168_().m_85836_();
|
||||
int centerX = x + width / 2;
|
||||
int centerY = y + height / 2;
|
||||
graphics.m_280168_().m_252880_((float)centerX, (float)centerY, 0.0f);
|
||||
graphics.m_280168_().m_85841_(scale, scale, 1.0f);
|
||||
graphics.m_280168_().m_252880_((float)(-width / 2), (float)(-height / 2), 0.0f);
|
||||
if (hovered) {
|
||||
int glowSize = 4;
|
||||
int glowAlpha = (int)(128.0f * alpha) << 24;
|
||||
graphics.m_280509_(-glowSize, -glowSize, width + glowSize, height + glowSize, accentColor & 0xFFFFFF | glowAlpha);
|
||||
}
|
||||
int bgAlpha = (int)(255.0f * alpha) << 24;
|
||||
graphics.m_280509_(0, 0, width, height, 0x591515 | bgAlpha);
|
||||
if (animator != null && animator.getTextureLocation() != null) {
|
||||
RenderSystem.enableBlend();
|
||||
RenderSystem.defaultBlendFunc();
|
||||
RenderSystem.setShaderColor((float)1.0f, (float)1.0f, (float)1.0f, (float)alpha);
|
||||
RenderSystem.setShaderTexture((int)0, (ResourceLocation)animator.getTextureLocation());
|
||||
graphics.m_280163_(animator.getTextureLocation(), 0, 0, 0.0f, 0.0f, width, height, width, height);
|
||||
RenderSystem.setShaderColor((float)1.0f, (float)1.0f, (float)1.0f, (float)1.0f);
|
||||
} else {
|
||||
int placeholderTextColor = (int)(150.0f * alpha) << 24 | 0xFFFFFFFF;
|
||||
String placeholder = "[Image not found]";
|
||||
int placeholderWidth = this.f_96547_.m_92895_(placeholder);
|
||||
graphics.m_280056_(this.f_96547_, placeholder, (width - placeholderWidth) / 2, height / 2 - 5, placeholderTextColor, false);
|
||||
}
|
||||
int borderColor = hovered ? accentColor : -2529701;
|
||||
int borderAlpha = (int)(255.0f * alpha) << 24;
|
||||
int fadedBorderColor = borderColor & 0xFFFFFF | borderAlpha;
|
||||
graphics.m_280509_(0, 0, width, 2, fadedBorderColor);
|
||||
graphics.m_280509_(0, height - 2, width, height, fadedBorderColor);
|
||||
graphics.m_280509_(0, 0, 2, height, fadedBorderColor);
|
||||
graphics.m_280509_(width - 2, 0, width, height, fadedBorderColor);
|
||||
graphics.m_280168_().m_85849_();
|
||||
int labelAlpha = (int)(255.0f * alpha) << 24;
|
||||
int labelColor = hovered ? accentColor : -1;
|
||||
int fadedLabelColor = labelColor & 0xFFFFFF | labelAlpha;
|
||||
int labelWidth = this.f_96547_.m_92895_(label);
|
||||
graphics.m_280056_(this.f_96547_, label, x + (width - labelWidth) / 2, y + height + 10, fadedLabelColor, true);
|
||||
}
|
||||
|
||||
public boolean m_6375_(double mouseX, double mouseY, int button) {
|
||||
if (this.fadingOut || this.isTransitioning) {
|
||||
return true;
|
||||
}
|
||||
if (button == 0) {
|
||||
if (this.currentState == ScreenState.CHOOSING_MODE) {
|
||||
if (this.isMouseOver((int)mouseX, (int)mouseY, this.leftBoxX, this.leftBoxY, this.leftBoxW, this.leftBoxH)) {
|
||||
this.selectRealisticMode();
|
||||
return true;
|
||||
}
|
||||
if (this.isMouseOver((int)mouseX, (int)mouseY, this.rightBoxX, this.rightBoxY, this.rightBoxW, this.rightBoxH)) {
|
||||
this.selectVanillaLike();
|
||||
return true;
|
||||
}
|
||||
if (this.isMouseOver((int)mouseX, (int)mouseY, this.bottomBoxX, this.bottomBoxY, this.bottomBoxW, this.bottomBoxH)) {
|
||||
this.selectRealistic2Mode();
|
||||
return true;
|
||||
}
|
||||
} else if (this.currentState == ScreenState.CHOOSING_STYLE) {
|
||||
if (this.isMouseOver((int)mouseX, (int)mouseY, this.leftBoxX, this.leftBoxY, this.leftBoxW, this.leftBoxH)) {
|
||||
this.selectStyle256();
|
||||
return true;
|
||||
}
|
||||
if (this.isMouseOver((int)mouseX, (int)mouseY, this.rightBoxX, this.rightBoxY, this.rightBoxW, this.rightBoxH)) {
|
||||
this.selectStyle64();
|
||||
return true;
|
||||
}
|
||||
if (this.isMouseOver((int)mouseX, (int)mouseY, this.backButtonX, this.backButtonY, this.backButtonW, this.backButtonH)) {
|
||||
this.goBack();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.m_6375_(mouseX, mouseY, button);
|
||||
}
|
||||
|
||||
private void selectRealisticMode() {
|
||||
this.playButtonSound();
|
||||
this.selectedRenderMode = Config.Client.ParticleRenderMode.REALISTIC;
|
||||
this.isTransitioning = true;
|
||||
this.transitionTime = 0.0f;
|
||||
this.transitionAlpha = 1.0f;
|
||||
}
|
||||
|
||||
private void selectRealistic2Mode() {
|
||||
this.playButtonSound();
|
||||
this.selectedRenderMode = Config.Client.ParticleRenderMode.REALISTIC_2;
|
||||
this.isTransitioning = true;
|
||||
this.transitionTime = 0.0f;
|
||||
this.transitionAlpha = 1.0f;
|
||||
}
|
||||
|
||||
private void selectStyle256() {
|
||||
this.playButtonSound();
|
||||
Config.CLIENT.glowTextureQuality.set((Object)Config.Client.GlowTextureQuality.QUALITY_256);
|
||||
Config.CLIENT.particleRenderMode.set((Object)this.selectedRenderMode);
|
||||
this.saveAndClose();
|
||||
}
|
||||
|
||||
private void selectStyle64() {
|
||||
this.playButtonSound();
|
||||
Config.CLIENT.glowTextureQuality.set((Object)Config.Client.GlowTextureQuality.QUALITY_64);
|
||||
Config.CLIENT.particleRenderMode.set((Object)this.selectedRenderMode);
|
||||
this.saveAndClose();
|
||||
}
|
||||
|
||||
private boolean isMouseOver(int mouseX, int mouseY, int x, int y, int width, int height) {
|
||||
return mouseX >= x && mouseX <= x + width && mouseY >= y && mouseY <= y + height;
|
||||
}
|
||||
|
||||
private void selectVanillaLike() {
|
||||
this.playButtonSound();
|
||||
Config.CLIENT.particleRenderMode.set((Object)Config.Client.ParticleRenderMode.VANILA);
|
||||
this.saveAndClose();
|
||||
}
|
||||
|
||||
private void goBack() {
|
||||
this.playButtonSound();
|
||||
this.isTransitioning = true;
|
||||
this.transitionTime = 0.0f;
|
||||
this.transitionAlpha = 1.0f;
|
||||
this.selectedRenderMode = null;
|
||||
}
|
||||
|
||||
private void saveAndClose() {
|
||||
Config.CLIENT.firstLaunchComplete.set((Object)true);
|
||||
Config.CLIENT_SPEC.save();
|
||||
ExplosionTextureManager.getInstance().reload();
|
||||
if (this.musicManager != null && this.musicManager.isPlaying()) {
|
||||
ExplosionOverhaul.LOGGER.info("Starting music and screen fade out (duration: {} seconds)", (Object)Float.valueOf(3.0f));
|
||||
this.musicManager.startFadeOut();
|
||||
}
|
||||
if (this.fadingIn) {
|
||||
this.fadingIn = false;
|
||||
ExplosionOverhaul.LOGGER.info("Interrupting fade in (was at {:.1f}%) to start fade out from current alpha", (Object)Float.valueOf(this.screenAlpha * 100.0f));
|
||||
}
|
||||
this.fadeOutStartAlpha = this.screenAlpha;
|
||||
this.fadingOut = true;
|
||||
this.fadeTime = 0.0f;
|
||||
this.fadeOutStartMillis = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
private void renderCinematicBackground(GuiGraphics graphics, float partialTick, float globalAlpha) {
|
||||
int i;
|
||||
int bgAlpha1;
|
||||
int bgColor1 = bgAlpha1 = (int)(255.0f * globalAlpha) << 24;
|
||||
int bgColor2 = 0xD0D0D | bgAlpha1;
|
||||
graphics.m_280024_(0, 0, this.f_96543_, this.f_96544_ / 2, bgColor1, bgColor2);
|
||||
graphics.m_280024_(0, this.f_96544_ / 2, this.f_96543_, this.f_96544_, bgColor2, bgColor1);
|
||||
RenderSystem.enableBlend();
|
||||
RenderSystem.defaultBlendFunc();
|
||||
for (BackgroundParticle p : this.particles) {
|
||||
float particleAlpha = p.getAlpha();
|
||||
float finalAlpha = particleAlpha * globalAlpha;
|
||||
int colorWithAlpha = p.color & 0xFFFFFF | (int)(finalAlpha * 255.0f) << 24;
|
||||
switch (p.type) {
|
||||
case SPARK: {
|
||||
float sparkLen = p.size * 3.0f;
|
||||
float sparkAngle = (float)Math.atan2(p.vy, p.vx);
|
||||
int ex = (int)((double)p.x + Math.cos(sparkAngle) * (double)sparkLen);
|
||||
int ey = (int)((double)p.y + Math.sin(sparkAngle) * (double)sparkLen);
|
||||
this.drawLine(graphics, (int)p.x, (int)p.y, ex, ey, colorWithAlpha);
|
||||
break;
|
||||
}
|
||||
case EMBER: {
|
||||
int emberSize = (int)p.size;
|
||||
graphics.m_280509_((int)p.x - emberSize, (int)p.y - emberSize, (int)p.x + emberSize, (int)p.y + emberSize, colorWithAlpha);
|
||||
break;
|
||||
}
|
||||
case FLASH: {
|
||||
int flashSize = (int)(p.size * 0.7f);
|
||||
int flashColor = colorWithAlpha & 0xFFFFFF | (int)(finalAlpha * 180.0f) << 24;
|
||||
graphics.m_280509_((int)p.x - flashSize, (int)p.y - flashSize, (int)p.x + flashSize, (int)p.y + flashSize, flashColor);
|
||||
break;
|
||||
}
|
||||
case SMOKE: {
|
||||
int smokeSize = (int)p.size;
|
||||
int smokeColor = colorWithAlpha & 0xFFFFFF | (int)(finalAlpha * 60.0f) << 24;
|
||||
graphics.m_280509_((int)p.x - smokeSize, (int)p.y - smokeSize, (int)p.x + smokeSize, (int)p.y + smokeSize, smokeColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
int vignetteSteps = 15;
|
||||
for (i = 0; i < vignetteSteps; ++i) {
|
||||
float ratio = (float)i / (float)vignetteSteps;
|
||||
int vignetteAlpha = (int)(ratio * ratio * 180.0f * globalAlpha);
|
||||
int vignetteColor = vignetteAlpha << 24;
|
||||
int thickness = 4;
|
||||
graphics.m_280509_(0, i * thickness, this.f_96543_, (i + 1) * thickness, vignetteColor);
|
||||
graphics.m_280509_(0, this.f_96544_ - (i + 1) * thickness, this.f_96543_, this.f_96544_ - i * thickness, vignetteColor);
|
||||
graphics.m_280509_(i * thickness, 0, (i + 1) * thickness, this.f_96544_, vignetteColor);
|
||||
graphics.m_280509_(this.f_96543_ - (i + 1) * thickness, 0, this.f_96543_ - i * thickness, this.f_96544_, vignetteColor);
|
||||
}
|
||||
for (i = 0; i < 150; ++i) {
|
||||
int gx = this.random.m_188503_(this.f_96543_);
|
||||
int gy = this.random.m_188503_(this.f_96544_);
|
||||
int grainAlpha = (int)((float)(20 + this.random.m_188503_(30)) * globalAlpha);
|
||||
int grainColor = grainAlpha << 24 | 0xFFFFFF;
|
||||
graphics.m_280509_(gx, gy, gx + 1, gy + 1, grainColor);
|
||||
}
|
||||
for (int y = 0; y < this.f_96544_; y += 4) {
|
||||
graphics.m_280509_(0, y, this.f_96543_, y + 1, 0x8000000);
|
||||
}
|
||||
RenderSystem.disableBlend();
|
||||
}
|
||||
|
||||
private void drawLine(GuiGraphics graphics, int x1, int y1, int x2, int y2, int color) {
|
||||
int dx = Math.abs(x2 - x1);
|
||||
int dy = Math.abs(y2 - y1);
|
||||
int sx = x1 < x2 ? 1 : -1;
|
||||
int sy = y1 < y2 ? 1 : -1;
|
||||
int err = dx - dy;
|
||||
for (int steps = 0; steps < 200; ++steps) {
|
||||
graphics.m_280509_(x1, y1, x1 + 1, y1 + 1, color);
|
||||
if (x1 == x2 && y1 == y2) break;
|
||||
int e2 = 2 * err;
|
||||
if (e2 > -dy) {
|
||||
err -= dy;
|
||||
x1 += sx;
|
||||
}
|
||||
if (e2 >= dx) continue;
|
||||
err += dx;
|
||||
y1 += sy;
|
||||
}
|
||||
}
|
||||
|
||||
public void m_7379_() {
|
||||
if (!this.fadingOut) {
|
||||
this.cleanupAnimators();
|
||||
super.m_7379_();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean m_7933_(int keyCode, int scanCode, int modifiers) {
|
||||
if (keyCode == 256) {
|
||||
return true;
|
||||
}
|
||||
return super.m_7933_(keyCode, scanCode, modifiers);
|
||||
}
|
||||
|
||||
public boolean m_7043_() {
|
||||
return true;
|
||||
}
|
||||
|
||||
private float easeOutCubic(float x) {
|
||||
return 1.0f - (float)Math.pow(1.0f - x, 3.0);
|
||||
}
|
||||
|
||||
private float easeInCubic(float x) {
|
||||
return x * x * x;
|
||||
}
|
||||
|
||||
private void renderBackButton(GuiGraphics graphics, float alpha) {
|
||||
graphics.m_280168_().m_85836_();
|
||||
int centerX = this.backButtonX + this.backButtonW / 2;
|
||||
int centerY = this.backButtonY + this.backButtonH / 2;
|
||||
graphics.m_280168_().m_252880_((float)centerX, (float)centerY, 0.0f);
|
||||
graphics.m_280168_().m_85841_(this.backButtonScale, this.backButtonScale, 1.0f);
|
||||
graphics.m_280168_().m_252880_((float)(-this.backButtonW / 2), (float)(-this.backButtonH / 2), 0.0f);
|
||||
if (this.backButtonHovered) {
|
||||
int glowSize = 3;
|
||||
int glowAlpha = (int)(128.0f * alpha) << 24;
|
||||
graphics.m_280509_(-glowSize, -glowSize, this.backButtonW + glowSize, this.backButtonH + glowSize, 0xF28B0C | glowAlpha);
|
||||
}
|
||||
int bgAlpha = (int)(255.0f * alpha) << 24;
|
||||
graphics.m_280509_(0, 0, this.backButtonW, this.backButtonH, 0x591515 | bgAlpha);
|
||||
int borderColor = this.backButtonHovered ? -881908 : -2529701;
|
||||
int borderAlpha = (int)(255.0f * alpha) << 24;
|
||||
int fadedBorderColor = borderColor & 0xFFFFFF | borderAlpha;
|
||||
graphics.m_280509_(0, 0, this.backButtonW, 2, fadedBorderColor);
|
||||
graphics.m_280509_(0, this.backButtonH - 2, this.backButtonW, this.backButtonH, fadedBorderColor);
|
||||
graphics.m_280509_(0, 0, 2, this.backButtonH, fadedBorderColor);
|
||||
graphics.m_280509_(this.backButtonW - 2, 0, this.backButtonW, this.backButtonH, fadedBorderColor);
|
||||
graphics.m_280168_().m_85849_();
|
||||
String buttonText = "BACK";
|
||||
int textWidth = this.f_96547_.m_92895_(buttonText);
|
||||
int textColor = this.backButtonHovered ? -881908 : -1;
|
||||
int textAlpha = (int)(255.0f * alpha) << 24;
|
||||
int fadedTextColor = textColor & 0xFFFFFF | textAlpha;
|
||||
graphics.m_280056_(this.f_96547_, buttonText, this.backButtonX + (this.backButtonW - textWidth) / 2, this.backButtonY + (this.backButtonH - 8) / 2, fadedTextColor, true);
|
||||
}
|
||||
|
||||
private void playButtonSound() {
|
||||
try {
|
||||
Minecraft minecraft = Minecraft.m_91087_();
|
||||
if (minecraft.m_91106_() != null) {
|
||||
minecraft.m_91106_().m_120367_((SoundInstance)SimpleSoundInstance.m_119755_((SoundEvent)((SoundEvent)ModSounds.BUTTON_SOUND.get()), (float)1.0f, (float)1.0f));
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
ExplosionOverhaul.LOGGER.warn("Failed to play button sound", (Throwable)e);
|
||||
}
|
||||
}
|
||||
|
||||
private static enum ScreenState {
|
||||
CHOOSING_MODE,
|
||||
CHOOSING_STYLE,
|
||||
FADING_OUT;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul.client;
|
||||
|
||||
import com.vinlanx.explosionoverhaul.Config;
|
||||
import com.vinlanx.explosionoverhaul.ExplosionOverhaul;
|
||||
import com.vinlanx.explosionoverhaul.client.IntroSplashScreen;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.screens.Screen;
|
||||
import net.minecraft.client.gui.screens.TitleScreen;
|
||||
import net.neoforged.api.distmarker.Dist;
|
||||
import net.neoforged.neoforge.event.TickEvent;
|
||||
import net.neoforged.bus.api.SubscribeEvent;
|
||||
import net.neoforged.fml.common.Mod;
|
||||
|
||||
@Mod.EventBusSubscriber(modid="explosionoverhaul", bus=Mod.EventBusSubscriber.Bus.FORGE, value={Dist.CLIENT})
|
||||
public class FirstTimeSetupHandler {
|
||||
private static boolean hasChecked = false;
|
||||
private static boolean pendingShowIntro = false;
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onClientTick(TickEvent.ClientTickEvent event) {
|
||||
if (event.phase != TickEvent.Phase.END) {
|
||||
return;
|
||||
}
|
||||
Minecraft mc = Minecraft.m_91087_();
|
||||
if (!hasChecked && mc.f_91080_ instanceof TitleScreen) {
|
||||
hasChecked = true;
|
||||
ExplosionOverhaul.LOGGER.info("Detected TitleScreen on client, hasChecked=true");
|
||||
if (Config.isFirstLaunch()) {
|
||||
pendingShowIntro = true;
|
||||
}
|
||||
}
|
||||
if (!pendingShowIntro) {
|
||||
return;
|
||||
}
|
||||
if (mc.f_91080_ instanceof TitleScreen) {
|
||||
pendingShowIntro = false;
|
||||
ExplosionOverhaul.LOGGER.info("Showing IntroSplashScreen (first launch)");
|
||||
mc.m_91152_((Screen)new IntroSplashScreen());
|
||||
}
|
||||
}
|
||||
|
||||
static {
|
||||
ExplosionOverhaul.LOGGER.info("FirstTimeSetupHandler class loaded (waiting for TitleScreen)");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul.client;
|
||||
|
||||
import com.vinlanx.explosionoverhaul.Config;
|
||||
import com.vinlanx.explosionoverhaul.SmokeParticleOptions;
|
||||
import com.vinlanx.explosionoverhaul.client.ExplosionWindController;
|
||||
import java.awt.Color;
|
||||
import java.util.Random;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.particles.ParticleOptions;
|
||||
import net.minecraft.tags.BlockTags;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.level.BlockGetter;
|
||||
import net.minecraft.world.level.ClipContext;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.material.MapColor;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraft.world.phys.HitResult;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
public class GroundDustEffect {
|
||||
private final ClientLevel level;
|
||||
private final Vec3 initialPosition;
|
||||
private final float power;
|
||||
private final Random random = new Random();
|
||||
private int age = 0;
|
||||
private final int maxAge;
|
||||
private final float maxRadius;
|
||||
private final float particleBaseSize;
|
||||
private final int particlesPerTick;
|
||||
private Color currentDustColor = new Color(128, 128, 128);
|
||||
private boolean finished = false;
|
||||
private final int raycastFrequency;
|
||||
|
||||
public GroundDustEffect(Vec3 position, float power) {
|
||||
this.level = Minecraft.m_91087_().f_91073_;
|
||||
this.initialPosition = position;
|
||||
this.power = power;
|
||||
double qualityMultiplier = (Double)Config.CLIENT.groundDustQuality.get();
|
||||
this.raycastFrequency = (Integer)Config.CLIENT.groundDustRaycastFrequency.get();
|
||||
float powerFraction = Mth.m_14036_((float)(power / 100.0f), (float)0.0f, (float)1.0f);
|
||||
int calculatedParticles = (int)((double)Mth.m_14179_((float)powerFraction, (float)40.0f, (float)200.0f) * qualityMultiplier);
|
||||
int calculatedMaxAge = (int)((double)Mth.m_14179_((float)powerFraction, (float)30.0f, (float)70.0f) * qualityMultiplier);
|
||||
if (qualityMultiplier > 0.0) {
|
||||
if (calculatedParticles == 0) {
|
||||
calculatedParticles = 1;
|
||||
}
|
||||
if (calculatedMaxAge == 0) {
|
||||
calculatedMaxAge = 1;
|
||||
}
|
||||
}
|
||||
this.particlesPerTick = calculatedParticles;
|
||||
this.maxAge = calculatedMaxAge;
|
||||
this.maxRadius = power * this.calculateRadiusMultiplier(power);
|
||||
this.particleBaseSize = Mth.m_14179_((float)powerFraction, (float)1.0f, (float)12.0f);
|
||||
}
|
||||
|
||||
private float calculateRadiusMultiplier(float power) {
|
||||
if (power <= 5.0f) {
|
||||
return 2.0f;
|
||||
}
|
||||
if (power <= 40.0f) {
|
||||
return Mth.m_14179_((float)((power - 5.0f) / 35.0f), (float)2.0f, (float)4.0f);
|
||||
}
|
||||
if (power <= 80.0f) {
|
||||
return Mth.m_14179_((float)((power - 40.0f) / 40.0f), (float)4.0f, (float)5.0f);
|
||||
}
|
||||
if (power <= 100.0f) {
|
||||
return Mth.m_14179_((float)((power - 80.0f) / 20.0f), (float)5.0f, (float)7.0f);
|
||||
}
|
||||
return 7.0f;
|
||||
}
|
||||
|
||||
private Color getDustColorForState(BlockState state) {
|
||||
if (state.m_204336_(BlockTags.f_13035_) || state.m_284242_((BlockGetter)this.level, BlockPos.f_121853_) == MapColor.f_283808_) {
|
||||
return null;
|
||||
}
|
||||
if (state.m_60713_(Blocks.f_50440_)) {
|
||||
return new Color(Blocks.f_50493_.m_49966_().m_284242_((BlockGetter)this.level, (BlockPos)BlockPos.f_121853_).f_283871_);
|
||||
}
|
||||
if (state.m_60713_(Blocks.f_50125_) || state.m_60713_(Blocks.f_50127_)) {
|
||||
return new Color(Blocks.f_50127_.m_49966_().m_284242_((BlockGetter)this.level, (BlockPos)BlockPos.f_121853_).f_283871_);
|
||||
}
|
||||
return new Color(state.m_284242_((BlockGetter)this.level, (BlockPos)BlockPos.f_121853_).f_283871_);
|
||||
}
|
||||
|
||||
public void tick() {
|
||||
BlockPos blockPos;
|
||||
BlockState blockState;
|
||||
Color newColor;
|
||||
double checkZ;
|
||||
double checkAngle;
|
||||
double checkX;
|
||||
BlockHitResult hitResult;
|
||||
if (this.finished || this.level == null) {
|
||||
return;
|
||||
}
|
||||
++this.age;
|
||||
if (this.age > this.maxAge) {
|
||||
this.finished = true;
|
||||
return;
|
||||
}
|
||||
float progress = (float)this.age / (float)this.maxAge;
|
||||
float easedProgress = 1.0f - (float)Math.pow(1.0f - progress, 3.0);
|
||||
float currentRadius = this.maxRadius * easedProgress;
|
||||
if (this.age % 10 == 0 && (hitResult = this.level.m_45547_(new ClipContext(new Vec3(checkX = this.initialPosition.f_82479_ + Math.cos(checkAngle = this.random.nextDouble() * 2.0 * Math.PI) * (double)currentRadius, this.initialPosition.f_82480_ + 15.0, checkZ = this.initialPosition.f_82481_ + Math.sin(checkAngle) * (double)currentRadius), new Vec3(checkX, this.initialPosition.f_82480_ - 15.0, checkZ), ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, null))).m_6662_() == HitResult.Type.BLOCK && (newColor = this.getDustColorForState(blockState = this.level.m_8055_(blockPos = hitResult.m_82425_()))) != null) {
|
||||
this.currentDustColor = newColor;
|
||||
}
|
||||
double cachedY = this.initialPosition.f_82480_;
|
||||
for (int i = 0; i < this.particlesPerTick; ++i) {
|
||||
float scale;
|
||||
float a;
|
||||
float r;
|
||||
float g;
|
||||
float b;
|
||||
double angle = (double)i / (double)this.particlesPerTick * 2.0 * Math.PI + (this.random.nextDouble() - 0.5) * 0.1;
|
||||
double radiusFrac = this.random.nextDouble();
|
||||
double spawnRadius = (double)currentRadius * (0.6 + radiusFrac * 0.4);
|
||||
double spawnX = this.initialPosition.f_82479_ + Math.cos(angle) * spawnRadius;
|
||||
double spawnZ = this.initialPosition.f_82481_ + Math.sin(angle) * spawnRadius;
|
||||
if (i % this.raycastFrequency == 0) {
|
||||
BlockHitResult hitResult2 = this.level.m_45547_(new ClipContext(new Vec3(spawnX, this.initialPosition.f_82480_ + 15.0, spawnZ), new Vec3(spawnX, this.initialPosition.f_82480_ - 15.0, spawnZ), ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, null));
|
||||
if (hitResult2.m_6662_() != HitResult.Type.BLOCK) continue;
|
||||
cachedY = hitResult2.m_82450_().f_82480_;
|
||||
}
|
||||
double spawnY = cachedY;
|
||||
Vec3 direction = new Vec3(spawnX - this.initialPosition.f_82479_, 0.0, spawnZ - this.initialPosition.f_82481_).m_82541_();
|
||||
double motionStrength = Mth.m_14179_((float)(1.0f - progress), (float)0.05f, (float)0.45f);
|
||||
double motionX = direction.f_82479_ * motionStrength + (this.random.nextDouble() - 0.5) * 0.05;
|
||||
double motionZ = direction.f_82481_ * motionStrength + (this.random.nextDouble() - 0.5) * 0.05;
|
||||
double motionY = (this.random.nextDouble() - 0.5) * 0.02;
|
||||
double heightPercent = 0.0;
|
||||
Vec3 windDirection = ExplosionWindController.getWindDirection();
|
||||
double windSpeed = ExplosionWindController.computeDustSpeed(0.0);
|
||||
double initialBoostFactor = 0.65;
|
||||
if (windDirection != Vec3.f_82478_ && windSpeed > 0.0) {
|
||||
motionX += windDirection.f_82479_ * windSpeed * initialBoostFactor;
|
||||
motionZ += windDirection.f_82481_ * windSpeed * initialBoostFactor;
|
||||
}
|
||||
int lifetime = 100 + this.random.nextInt(60);
|
||||
if (radiusFrac <= 0.2) {
|
||||
b = 0.2f;
|
||||
g = 0.2f;
|
||||
r = 0.2f;
|
||||
a = 0.9f;
|
||||
scale = this.particleBaseSize * 0.5f;
|
||||
} else if (radiusFrac <= 0.65) {
|
||||
b = 0.4f;
|
||||
g = 0.4f;
|
||||
r = 0.4f;
|
||||
a = 0.6f;
|
||||
scale = this.particleBaseSize * 0.75f;
|
||||
} else {
|
||||
r = (float)this.currentDustColor.getRed() / 255.0f;
|
||||
g = (float)this.currentDustColor.getGreen() / 255.0f;
|
||||
b = (float)this.currentDustColor.getBlue() / 255.0f;
|
||||
a = 0.35f;
|
||||
scale = this.particleBaseSize;
|
||||
}
|
||||
SmokeParticleOptions options = new SmokeParticleOptions(scale * (0.8f + this.random.nextFloat() * 0.4f), lifetime, r, g, b, a, false, (float)windSpeed, (float)heightPercent, null);
|
||||
this.level.m_6493_((ParticleOptions)options, true, spawnX, spawnY + 0.2, spawnZ, motionX, motionY, motionZ);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isFinished() {
|
||||
return this.finished;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul.client;
|
||||
|
||||
import com.vinlanx.explosionoverhaul.Config;
|
||||
import com.vinlanx.explosionoverhaul.SmokeParticleOptions;
|
||||
import java.awt.Color;
|
||||
import java.util.Random;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.particles.ParticleOptions;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.level.ClipContext;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraft.world.phys.HitResult;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
public class GroundMistEffect {
|
||||
private final ClientLevel level;
|
||||
private final Vec3 initialPosition;
|
||||
private final float power;
|
||||
private final Random random = new Random();
|
||||
private int age = 0;
|
||||
private final int maxAge;
|
||||
private final float maxRadius;
|
||||
private final float particleBaseSize;
|
||||
private final int particlesPerTick;
|
||||
private Color currentMistColor = new Color(255, 255, 255);
|
||||
private boolean finished = false;
|
||||
private final int raycastFrequency;
|
||||
|
||||
public GroundMistEffect(Vec3 position, float power) {
|
||||
this.level = Minecraft.m_91087_().f_91073_;
|
||||
this.initialPosition = position;
|
||||
this.power = power;
|
||||
double qualityMultiplier = (Double)Config.CLIENT.groundMistQuality.get();
|
||||
this.raycastFrequency = (Integer)Config.CLIENT.groundMistRaycastFrequency.get();
|
||||
float powerFraction = Mth.m_14036_((float)(power / 100.0f), (float)0.0f, (float)1.0f);
|
||||
int calculatedParticles = (int)((double)Mth.m_14179_((float)powerFraction, (float)40.0f, (float)200.0f) * qualityMultiplier * 1.5);
|
||||
int calculatedMaxAge = (int)((double)Mth.m_14179_((float)powerFraction, (float)30.0f, (float)70.0f) * qualityMultiplier / 3.0);
|
||||
if (qualityMultiplier > 0.0) {
|
||||
if (calculatedParticles == 0) {
|
||||
calculatedParticles = 1;
|
||||
}
|
||||
if (calculatedMaxAge == 0) {
|
||||
calculatedMaxAge = 1;
|
||||
}
|
||||
}
|
||||
this.particlesPerTick = calculatedParticles;
|
||||
this.maxAge = calculatedMaxAge;
|
||||
this.maxRadius = power * this.calculateRadiusMultiplier(power) * 3.0f;
|
||||
this.particleBaseSize = Mth.m_14179_((float)powerFraction, (float)1.0f, (float)12.0f);
|
||||
}
|
||||
|
||||
private float calculateRadiusMultiplier(float power) {
|
||||
if (power <= 5.0f) {
|
||||
return 2.0f;
|
||||
}
|
||||
if (power <= 40.0f) {
|
||||
return Mth.m_14179_((float)((power - 5.0f) / 35.0f), (float)2.0f, (float)4.0f);
|
||||
}
|
||||
if (power <= 80.0f) {
|
||||
return Mth.m_14179_((float)((power - 40.0f) / 40.0f), (float)4.0f, (float)5.0f);
|
||||
}
|
||||
if (power <= 100.0f) {
|
||||
return Mth.m_14179_((float)((power - 80.0f) / 20.0f), (float)5.0f, (float)7.0f);
|
||||
}
|
||||
return 7.0f;
|
||||
}
|
||||
|
||||
public void tick() {
|
||||
double checkZ;
|
||||
double checkAngle;
|
||||
double checkX;
|
||||
BlockHitResult hitResult;
|
||||
if (this.finished || this.level == null) {
|
||||
return;
|
||||
}
|
||||
++this.age;
|
||||
if (this.age > this.maxAge) {
|
||||
this.finished = true;
|
||||
return;
|
||||
}
|
||||
float progress = (float)this.age / (float)this.maxAge;
|
||||
float easedProgress = 1.0f - (float)Math.pow(1.0f - progress, 3.0);
|
||||
float currentRadius = this.maxRadius * easedProgress;
|
||||
if (this.age % 10 == 0 && (hitResult = this.level.m_45547_(new ClipContext(new Vec3(checkX = this.initialPosition.f_82479_ + Math.cos(checkAngle = this.random.nextDouble() * 2.0 * Math.PI) * (double)currentRadius, this.initialPosition.f_82480_ + 15.0, checkZ = this.initialPosition.f_82481_ + Math.sin(checkAngle) * (double)currentRadius), new Vec3(checkX, this.initialPosition.f_82480_ - 15.0, checkZ), ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, null))).m_6662_() == HitResult.Type.BLOCK) {
|
||||
BlockPos blockPos = hitResult.m_82425_();
|
||||
BlockState blockState = this.level.m_8055_(blockPos);
|
||||
}
|
||||
double cachedY = this.initialPosition.f_82480_;
|
||||
for (int i = 0; i < this.particlesPerTick; ++i) {
|
||||
float scale;
|
||||
float a;
|
||||
float r;
|
||||
float g;
|
||||
float b;
|
||||
double angle = (double)i / (double)this.particlesPerTick * 2.0 * Math.PI + (this.random.nextDouble() - 0.5) * 0.1;
|
||||
double radiusFrac = this.random.nextDouble();
|
||||
double spawnRadius = (double)currentRadius * (0.6 + radiusFrac * 0.4);
|
||||
double spawnX = this.initialPosition.f_82479_ + Math.cos(angle) * spawnRadius;
|
||||
double spawnZ = this.initialPosition.f_82481_ + Math.sin(angle) * spawnRadius;
|
||||
if (i % this.raycastFrequency == 0) {
|
||||
BlockHitResult hitResult2 = this.level.m_45547_(new ClipContext(new Vec3(spawnX, this.initialPosition.f_82480_ + 15.0, spawnZ), new Vec3(spawnX, this.initialPosition.f_82480_ - 15.0, spawnZ), ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, null));
|
||||
if (hitResult2.m_6662_() != HitResult.Type.BLOCK) continue;
|
||||
cachedY = hitResult2.m_82450_().f_82480_;
|
||||
}
|
||||
double spawnY = cachedY;
|
||||
Vec3 direction = new Vec3(spawnX - this.initialPosition.f_82479_, 0.0, spawnZ - this.initialPosition.f_82481_).m_82541_();
|
||||
double motionStrength = Mth.m_14179_((float)(1.0f - progress), (float)0.02f, (float)0.15f);
|
||||
double motionX = direction.f_82479_ * motionStrength + (this.random.nextDouble() - 0.5) * 0.02;
|
||||
double motionZ = direction.f_82481_ * motionStrength + (this.random.nextDouble() - 0.5) * 0.02;
|
||||
double motionY = -0.01 - this.random.nextDouble() * 0.02;
|
||||
int lifetime = 100 + this.random.nextInt(60);
|
||||
if (radiusFrac <= 0.2) {
|
||||
b = 0.8f;
|
||||
g = 0.8f;
|
||||
r = 0.8f;
|
||||
a = 0.3f;
|
||||
scale = this.particleBaseSize * 0.1667f;
|
||||
} else if (radiusFrac <= 0.65) {
|
||||
b = 0.9f;
|
||||
g = 0.9f;
|
||||
r = 0.9f;
|
||||
a = 0.2f;
|
||||
scale = this.particleBaseSize * 0.25f;
|
||||
} else {
|
||||
r = (float)this.currentMistColor.getRed() / 255.0f;
|
||||
g = (float)this.currentMistColor.getGreen() / 255.0f;
|
||||
b = (float)this.currentMistColor.getBlue() / 255.0f;
|
||||
a = 0.15f;
|
||||
scale = this.particleBaseSize * 0.333f;
|
||||
}
|
||||
SmokeParticleOptions options = new SmokeParticleOptions(scale * (0.8f + this.random.nextFloat() * 0.4f), lifetime, r, g, b, a, false, 0.0f, 0.0f, null);
|
||||
this.level.m_6493_((ParticleOptions)options, true, spawnX, spawnY + 0.05, spawnZ, motionX, motionY, motionZ);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isFinished() {
|
||||
return this.finished;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,633 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul.client;
|
||||
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.vinlanx.explosionoverhaul.ExplosionOverhaul;
|
||||
import com.vinlanx.explosionoverhaul.ModSounds;
|
||||
import com.vinlanx.explosionoverhaul.client.AnimationSoundManager;
|
||||
import com.vinlanx.explosionoverhaul.client.BackgroundParticle;
|
||||
import com.vinlanx.explosionoverhaul.client.FirstTimeScreen;
|
||||
import com.vinlanx.explosionoverhaul.client.IntroMusicManager;
|
||||
import com.vinlanx.explosionoverhaul.client.SpriteSheetAnimator;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Queue;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiGraphics;
|
||||
import net.minecraft.client.gui.screens.Screen;
|
||||
import net.minecraft.client.renderer.GameRenderer;
|
||||
import net.minecraft.client.resources.sounds.SimpleSoundInstance;
|
||||
import net.minecraft.client.resources.sounds.SoundInstance;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.sounds.SoundEvent;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.util.RandomSource;
|
||||
|
||||
public class GuideSlidesScreen
|
||||
extends Screen {
|
||||
private static final SlideData[] SLIDES = new SlideData[]{new SlideData("claster_slide.png", 177, "Cluster TNT \u2013 If you place more than two TNT blocks next to each other, the explosion will be much stronger!"), new SlideData("cave_slide.png", 121, "Caves \u2013 If an explosion happens on the surface while you're underground, you'll hear a terrifying rumble, and the ground and dripstones will start to crumble!"), new SlideData("glass_slide.png", 98, "Glass Shattering \u2013 Explosions create shockwaves! Be careful when working with explosives near settlements."), new SlideData("lamp_slide.png", 154, "Lamp Flickering \u2013 If an explosion happens near lamps, the lights will start to flicker."), new SlideData("speed_of_sound_slide.png", 140, "Speed of Sound \u2013 Explosions travel at the speed of sound. You can also enable \"Epic Mode\" in the settings!")};
|
||||
private static final int FRAME_WIDTH = 854;
|
||||
private static final int FRAME_HEIGHT = 480;
|
||||
private static final int COLUMNS = 14;
|
||||
private static final int ROWS = 14;
|
||||
private static final int FPS = 24;
|
||||
private static final int COLOR_BG = -15921907;
|
||||
private static final int COLOR_ACCENT_ORANGE = -881908;
|
||||
private static final int COLOR_ACCENT_RED = -4250588;
|
||||
private static final int COLOR_ACCENT_ROSE = -2529701;
|
||||
private static final int COLOR_ACCENT_DARK_RED = -10939115;
|
||||
private static final int COLOR_TEXT = -1;
|
||||
private static final int COLOR_PROGRESS_BG = Integer.MIN_VALUE;
|
||||
private static final int COLOR_PROGRESS_FILL = -881908;
|
||||
private static final float FADE_IN_DURATION = 1.5f;
|
||||
private static final float SLIDE_TRANSITION_DURATION = 1.0f;
|
||||
private static final float AUTO_ADVANCE_DELAY = 0.5f;
|
||||
private int currentSlideIndex = 0;
|
||||
private SpriteSheetAnimator currentAnimator;
|
||||
private float fadeAlpha = 0.0f;
|
||||
private boolean fadingIn = true;
|
||||
private float fadeTime = 0.0f;
|
||||
private boolean isTransitioning = false;
|
||||
private float transitionTime = 0.0f;
|
||||
private int transitionToIndex = -1;
|
||||
private float transitionAlpha = 0.0f;
|
||||
private SpriteSheetAnimator nextAnimator;
|
||||
private float autoAdvanceTimer = 0.0f;
|
||||
private boolean waitingForAutoAdvance = false;
|
||||
private Queue<Integer> transitionQueue = new LinkedList<Integer>();
|
||||
private int animationX;
|
||||
private int animationY;
|
||||
private int animationWidth;
|
||||
private int animationHeight;
|
||||
private int progressBarX;
|
||||
private int progressBarY;
|
||||
private int progressBarWidth;
|
||||
private int progressBarHeight;
|
||||
private int leftArrowX;
|
||||
private int leftArrowY;
|
||||
private int arrowSize;
|
||||
private int rightArrowX;
|
||||
private int rightArrowY;
|
||||
private boolean leftArrowHovered = false;
|
||||
private boolean rightArrowHovered = false;
|
||||
private float leftArrowScale = 1.0f;
|
||||
private float rightArrowScale = 1.0f;
|
||||
private int continueButtonX;
|
||||
private int continueButtonY;
|
||||
private int continueButtonWidth;
|
||||
private int continueButtonHeight;
|
||||
private boolean continueButtonHovered = false;
|
||||
private float continueButtonScale = 1.0f;
|
||||
private List<BackgroundParticle> particles = new ArrayList<BackgroundParticle>();
|
||||
private RandomSource random = RandomSource.m_216327_();
|
||||
private long lastFrameTime = System.currentTimeMillis();
|
||||
private IntroMusicManager musicManager;
|
||||
|
||||
public GuideSlidesScreen() {
|
||||
super((Component)Component.m_237113_((String)"Guide Slides"));
|
||||
}
|
||||
|
||||
protected void m_7856_() {
|
||||
int i;
|
||||
super.m_7856_();
|
||||
this.fadingIn = true;
|
||||
this.fadeTime = 0.0f;
|
||||
this.fadeAlpha = 0.0f;
|
||||
this.isTransitioning = false;
|
||||
this.waitingForAutoAdvance = false;
|
||||
this.autoAdvanceTimer = 0.0f;
|
||||
this.lastFrameTime = System.currentTimeMillis();
|
||||
this.musicManager = IntroMusicManager.getInstance();
|
||||
this.loadSlide(this.currentSlideIndex);
|
||||
int maxWidth = (int)((float)this.f_96543_ * 0.76f);
|
||||
int maxHeight = (int)((float)this.f_96544_ * 0.65f);
|
||||
float aspectRatio = 1.7791667f;
|
||||
if ((float)maxWidth / aspectRatio <= (float)maxHeight) {
|
||||
this.animationWidth = maxWidth;
|
||||
this.animationHeight = (int)((float)maxWidth / aspectRatio);
|
||||
} else {
|
||||
this.animationHeight = maxHeight;
|
||||
this.animationWidth = (int)((float)maxHeight * aspectRatio);
|
||||
}
|
||||
this.animationX = (this.f_96543_ - this.animationWidth) / 2;
|
||||
this.animationY = (int)((float)this.f_96544_ * 0.12f);
|
||||
this.progressBarWidth = this.animationWidth;
|
||||
this.progressBarHeight = (int)((float)this.f_96544_ * 0.025f);
|
||||
this.progressBarX = this.animationX;
|
||||
this.progressBarY = this.animationY + this.animationHeight + (int)((float)this.f_96544_ * 0.03f);
|
||||
this.arrowSize = (int)((float)this.f_96544_ * 0.08f);
|
||||
int arrowGap = (int)((float)this.f_96543_ * 0.02f);
|
||||
this.leftArrowX = this.animationX - this.arrowSize - arrowGap;
|
||||
this.leftArrowY = this.animationY + (this.animationHeight - this.arrowSize) / 2;
|
||||
this.rightArrowX = this.animationX + this.animationWidth + arrowGap;
|
||||
this.rightArrowY = this.animationY + (this.animationHeight - this.arrowSize) / 2;
|
||||
this.continueButtonWidth = (int)((float)this.f_96543_ * 0.15f);
|
||||
this.continueButtonHeight = (int)((float)this.f_96544_ * 0.06f);
|
||||
this.continueButtonX = (this.f_96543_ - this.continueButtonWidth) / 2;
|
||||
this.continueButtonY = (int)((float)this.f_96544_ * 0.88f);
|
||||
for (i = 0; i < 30; ++i) {
|
||||
this.particles.add(BackgroundParticle.createSpark(this.random, this.f_96543_, this.f_96544_));
|
||||
}
|
||||
for (i = 0; i < 10; ++i) {
|
||||
this.particles.add(BackgroundParticle.createEmber(this.random, this.f_96543_, this.f_96544_));
|
||||
}
|
||||
for (i = 0; i < 5; ++i) {
|
||||
this.particles.add(BackgroundParticle.createSmoke(this.random, this.f_96543_, this.f_96544_));
|
||||
}
|
||||
}
|
||||
|
||||
private void loadSlide(int index) {
|
||||
if (index < 0 || index >= SLIDES.length) {
|
||||
return;
|
||||
}
|
||||
if (this.currentAnimator != null) {
|
||||
this.currentAnimator.close();
|
||||
}
|
||||
SlideData slide = SLIDES[index];
|
||||
this.currentAnimator = new SpriteSheetAnimator(slide.spriteSheet, 854, 480, 14, 14, slide.totalFrames, 24);
|
||||
this.currentAnimator.load();
|
||||
this.registerSoundCallbacks(index, this.currentAnimator);
|
||||
this.currentAnimator.play();
|
||||
ExplosionOverhaul.LOGGER.info("Loaded guide slide {} - texture created fresh", (Object)index);
|
||||
}
|
||||
|
||||
private void registerSoundCallbacks(int slideIndex, SpriteSheetAnimator animator) {
|
||||
switch (slideIndex) {
|
||||
case 0: {
|
||||
animator.registerFrameCallback(43, AnimationSoundManager::playRandomFarPower2Sound);
|
||||
animator.registerFrameCallback(132, AnimationSoundManager::playRandomSuperfar4Sound);
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
animator.registerFrameCallback(43, AnimationSoundManager::playRandomMediumCavePower4Sound);
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
animator.registerFrameCallback(30, AnimationSoundManager::playRandomFarPower3Sound);
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
animator.registerFrameCallback(34, AnimationSoundManager::playRandomFarPower2Sound);
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
animator.registerFrameCallback(30, AnimationSoundManager::playRandomFarPower2Sound);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void m_86600_() {
|
||||
float progress;
|
||||
super.m_86600_();
|
||||
long currentTime = System.currentTimeMillis();
|
||||
float deltaTime = Math.min((float)(currentTime - this.lastFrameTime) / 1000.0f, 0.1f);
|
||||
this.lastFrameTime = currentTime;
|
||||
if (this.fadingIn) {
|
||||
this.fadeTime += deltaTime;
|
||||
progress = Math.min(1.0f, this.fadeTime / 1.5f);
|
||||
this.fadeAlpha = this.easeOutCubic(progress);
|
||||
if (this.fadeTime >= 1.5f) {
|
||||
this.fadingIn = false;
|
||||
this.fadeAlpha = 1.0f;
|
||||
}
|
||||
}
|
||||
if (this.isTransitioning) {
|
||||
this.transitionTime += deltaTime;
|
||||
progress = Math.min(1.0f, this.transitionTime / 1.0f);
|
||||
this.transitionAlpha = this.easeInOutCubic(progress);
|
||||
if (this.transitionTime >= 1.0f) {
|
||||
this.isTransitioning = false;
|
||||
this.currentSlideIndex = this.transitionToIndex;
|
||||
if (this.currentAnimator != null) {
|
||||
this.currentAnimator.close();
|
||||
}
|
||||
this.currentAnimator = this.nextAnimator;
|
||||
this.nextAnimator = null;
|
||||
this.transitionToIndex = -1;
|
||||
this.waitingForAutoAdvance = false;
|
||||
this.autoAdvanceTimer = 0.0f;
|
||||
ExplosionOverhaul.LOGGER.info("Transition complete to slide {}", (Object)this.currentSlideIndex);
|
||||
if (!this.transitionQueue.isEmpty()) {
|
||||
int nextIndex = this.transitionQueue.poll();
|
||||
ExplosionOverhaul.LOGGER.info("Processing queued transition to slide {}", (Object)nextIndex);
|
||||
this.startTransition(nextIndex);
|
||||
}
|
||||
} else if (this.transitionAlpha >= 0.5f && this.nextAnimator == null && this.transitionToIndex >= 0 && this.transitionToIndex < SLIDES.length) {
|
||||
SlideData slide = SLIDES[this.transitionToIndex];
|
||||
this.nextAnimator = new SpriteSheetAnimator(slide.spriteSheet, 854, 480, 14, 14, slide.totalFrames, 24);
|
||||
this.nextAnimator.load();
|
||||
this.registerSoundCallbacks(this.transitionToIndex, this.nextAnimator);
|
||||
this.nextAnimator.play();
|
||||
ExplosionOverhaul.LOGGER.info("Created next slide {} animator at transition midpoint", (Object)this.transitionToIndex);
|
||||
}
|
||||
}
|
||||
if (this.currentAnimator != null && !this.isTransitioning) {
|
||||
this.currentAnimator.tick(deltaTime);
|
||||
}
|
||||
float scaleSpeed = 0.2f;
|
||||
float targetScale = 1.1f;
|
||||
this.leftArrowScale = Mth.m_14179_((float)scaleSpeed, (float)this.leftArrowScale, (float)(this.leftArrowHovered ? targetScale : 1.0f));
|
||||
this.rightArrowScale = Mth.m_14179_((float)scaleSpeed, (float)this.rightArrowScale, (float)(this.rightArrowHovered ? targetScale : 1.0f));
|
||||
this.continueButtonScale = Mth.m_14179_((float)scaleSpeed, (float)this.continueButtonScale, (float)(this.continueButtonHovered ? targetScale : 1.0f));
|
||||
this.particles.removeIf(p -> {
|
||||
p.tick(deltaTime);
|
||||
return p.isDead() || p.x < -50.0f || p.x > (float)(this.f_96543_ + 50) || p.y < -50.0f || p.y > (float)(this.f_96544_ + 50);
|
||||
});
|
||||
if (this.random.m_188501_() < 0.1f) {
|
||||
this.particles.add(BackgroundParticle.createSpark(this.random, this.f_96543_, this.f_96544_));
|
||||
}
|
||||
if (this.random.m_188501_() < 0.03f) {
|
||||
this.particles.add(BackgroundParticle.createEmber(this.random, this.f_96543_, this.f_96544_));
|
||||
}
|
||||
if (this.random.m_188501_() < 0.01f) {
|
||||
this.particles.add(BackgroundParticle.createSmoke(this.random, this.f_96543_, this.f_96544_));
|
||||
}
|
||||
if (this.musicManager != null) {
|
||||
this.musicManager.tick(deltaTime);
|
||||
}
|
||||
}
|
||||
|
||||
private void startTransition(int toIndex) {
|
||||
if (toIndex < 0 || toIndex >= SLIDES.length || this.isTransitioning) {
|
||||
return;
|
||||
}
|
||||
this.isTransitioning = true;
|
||||
this.transitionTime = 0.0f;
|
||||
this.transitionAlpha = 0.0f;
|
||||
this.transitionToIndex = toIndex;
|
||||
this.waitingForAutoAdvance = false;
|
||||
this.autoAdvanceTimer = 0.0f;
|
||||
ExplosionOverhaul.LOGGER.info("Starting transition from slide {} to {}", (Object)this.currentSlideIndex, (Object)toIndex);
|
||||
}
|
||||
|
||||
public void m_88315_(GuiGraphics graphics, int mouseX, int mouseY, float partialTick) {
|
||||
graphics.m_280509_(0, 0, this.f_96543_, this.f_96544_, -15921907);
|
||||
if (this.fadeAlpha < 0.01f) {
|
||||
return;
|
||||
}
|
||||
RenderSystem.enableBlend();
|
||||
RenderSystem.defaultBlendFunc();
|
||||
this.renderBackgroundParticles(graphics, this.fadeAlpha * 0.6f);
|
||||
if (this.isTransitioning) {
|
||||
float currentAlpha = 1.0f - this.transitionAlpha;
|
||||
float nextAlpha = this.transitionAlpha;
|
||||
if (this.currentAnimator != null && currentAlpha > 0.01f) {
|
||||
this.renderAnimation(graphics, this.currentAnimator, this.fadeAlpha * currentAlpha);
|
||||
}
|
||||
if (this.nextAnimator != null && nextAlpha > 0.01f) {
|
||||
this.renderAnimation(graphics, this.nextAnimator, this.fadeAlpha * nextAlpha);
|
||||
}
|
||||
} else if (this.currentAnimator != null) {
|
||||
this.renderAnimation(graphics, this.currentAnimator, this.fadeAlpha);
|
||||
}
|
||||
this.renderGuideText(graphics, this.fadeAlpha);
|
||||
this.renderArrows(graphics, mouseX, mouseY, this.fadeAlpha);
|
||||
this.renderContinueButton(graphics, mouseX, mouseY, this.fadeAlpha);
|
||||
RenderSystem.disableBlend();
|
||||
}
|
||||
|
||||
private void renderBackgroundParticles(GuiGraphics graphics, float alpha) {
|
||||
for (BackgroundParticle p : this.particles) {
|
||||
float particleAlpha = p.getAlpha();
|
||||
float finalAlpha = particleAlpha * alpha;
|
||||
int colorWithAlpha = p.color & 0xFFFFFF | (int)(finalAlpha * 255.0f) << 24;
|
||||
switch (p.type) {
|
||||
case SPARK: {
|
||||
float sparkLen = p.size * 3.0f;
|
||||
float sparkAngle = (float)Math.atan2(p.vy, p.vx);
|
||||
int ex = (int)((double)p.x + Math.cos(sparkAngle) * (double)sparkLen);
|
||||
int ey = (int)((double)p.y + Math.sin(sparkAngle) * (double)sparkLen);
|
||||
this.drawLine(graphics, (int)p.x, (int)p.y, ex, ey, colorWithAlpha);
|
||||
break;
|
||||
}
|
||||
case EMBER: {
|
||||
int emberSize = (int)p.size;
|
||||
graphics.m_280509_((int)p.x - emberSize, (int)p.y - emberSize, (int)p.x + emberSize, (int)p.y + emberSize, colorWithAlpha);
|
||||
break;
|
||||
}
|
||||
case FLASH: {
|
||||
int flashSize = (int)(p.size * 0.7f);
|
||||
int flashColor = colorWithAlpha & 0xFFFFFF | (int)(finalAlpha * 180.0f) << 24;
|
||||
graphics.m_280509_((int)p.x - flashSize, (int)p.y - flashSize, (int)p.x + flashSize, (int)p.y + flashSize, flashColor);
|
||||
break;
|
||||
}
|
||||
case SMOKE: {
|
||||
int smokeSize = (int)p.size;
|
||||
int smokeColor = colorWithAlpha & 0xFFFFFF | (int)(finalAlpha * 60.0f) << 24;
|
||||
graphics.m_280509_((int)p.x - smokeSize, (int)p.y - smokeSize, (int)p.x + smokeSize, (int)p.y + smokeSize, smokeColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void renderAnimation(GuiGraphics graphics, SpriteSheetAnimator animator, float alpha) {
|
||||
ResourceLocation texture = animator.getTextureLocation();
|
||||
if (texture == null) {
|
||||
return;
|
||||
}
|
||||
RenderSystem.setShader(GameRenderer::m_172817_);
|
||||
RenderSystem.setShaderTexture((int)0, (ResourceLocation)texture);
|
||||
RenderSystem.setShaderColor((float)1.0f, (float)1.0f, (float)1.0f, (float)alpha);
|
||||
graphics.m_280411_(texture, this.animationX, this.animationY, this.animationWidth, this.animationHeight, 0.0f, 0.0f, 854, 480, 854, 480);
|
||||
int glowColor = (int)(alpha * 32.0f) << 24 | 0xF28B0C;
|
||||
int borderThickness = 2;
|
||||
graphics.m_280509_(this.animationX - borderThickness, this.animationY - borderThickness, this.animationX + this.animationWidth + borderThickness, this.animationY, glowColor);
|
||||
graphics.m_280509_(this.animationX - borderThickness, this.animationY + this.animationHeight, this.animationX + this.animationWidth + borderThickness, this.animationY + this.animationHeight + borderThickness, glowColor);
|
||||
graphics.m_280509_(this.animationX - borderThickness, this.animationY, this.animationX, this.animationY + this.animationHeight, glowColor);
|
||||
graphics.m_280509_(this.animationX + this.animationWidth, this.animationY, this.animationX + this.animationWidth + borderThickness, this.animationY + this.animationHeight, glowColor);
|
||||
}
|
||||
|
||||
private void renderProgressBar(GuiGraphics graphics, float alpha) {
|
||||
if (this.currentAnimator == null) {
|
||||
return;
|
||||
}
|
||||
int currentFrame = this.currentAnimator.getCurrentFrame();
|
||||
int totalFrames = GuideSlidesScreen.SLIDES[this.currentSlideIndex].totalFrames;
|
||||
float progress = (float)currentFrame / (float)totalFrames;
|
||||
int bgColor = (int)(alpha * 128.0f) << 24 | 0;
|
||||
graphics.m_280509_(this.progressBarX, this.progressBarY, this.progressBarX + this.progressBarWidth, this.progressBarY + this.progressBarHeight, bgColor);
|
||||
int fillWidth = (int)((float)this.progressBarWidth * progress);
|
||||
int fillColor = (int)(alpha * 255.0f) << 24 | 0xF28B0C;
|
||||
graphics.m_280509_(this.progressBarX, this.progressBarY, this.progressBarX + fillWidth, this.progressBarY + this.progressBarHeight, fillColor);
|
||||
if (fillWidth > 0) {
|
||||
int glowColor = (int)(alpha * 64.0f) << 24 | 0xF28B0C;
|
||||
graphics.m_280509_(this.progressBarX + fillWidth - 4, this.progressBarY - 1, this.progressBarX + fillWidth, this.progressBarY + this.progressBarHeight + 1, glowColor);
|
||||
}
|
||||
}
|
||||
|
||||
private void renderGuideText(GuiGraphics graphics, float alpha) {
|
||||
String text = GuideSlidesScreen.SLIDES[this.currentSlideIndex].guideText;
|
||||
int textColor = (int)(alpha * 255.0f) << 24 | 0xFFFFFF;
|
||||
int textY = this.animationY + this.animationHeight + (int)((float)this.f_96544_ * 0.04f);
|
||||
int maxLineWidth = this.animationWidth;
|
||||
List<String> lines = this.wrapText(text, maxLineWidth);
|
||||
Objects.requireNonNull(this.f_96547_);
|
||||
int lineHeight = 9 + 4;
|
||||
int totalTextHeight = lines.size() * lineHeight;
|
||||
int startY = textY;
|
||||
for (int i = 0; i < lines.size(); ++i) {
|
||||
String line = lines.get(i);
|
||||
int lineWidth = this.f_96547_.m_92895_(line);
|
||||
int x = this.animationX + (this.animationWidth - lineWidth) / 2;
|
||||
graphics.m_280056_(this.f_96547_, line, x, startY + i * lineHeight, textColor, true);
|
||||
}
|
||||
}
|
||||
|
||||
private List<String> wrapText(String text, int maxWidth) {
|
||||
ArrayList<String> lines = new ArrayList<String>();
|
||||
String[] words = text.split(" ");
|
||||
StringBuilder currentLine = new StringBuilder();
|
||||
for (String word : words) {
|
||||
Object testLine = currentLine.length() > 0 ? currentLine + " " + word : word;
|
||||
int width = this.f_96547_.m_92895_((String)testLine);
|
||||
if (width > maxWidth && currentLine.length() > 0) {
|
||||
lines.add(currentLine.toString());
|
||||
currentLine = new StringBuilder(word);
|
||||
continue;
|
||||
}
|
||||
if (currentLine.length() > 0) {
|
||||
currentLine.append(" ");
|
||||
}
|
||||
currentLine.append(word);
|
||||
}
|
||||
if (currentLine.length() > 0) {
|
||||
lines.add(currentLine.toString());
|
||||
}
|
||||
return lines;
|
||||
}
|
||||
|
||||
private void renderArrows(GuiGraphics graphics, int mouseX, int mouseY, float alpha) {
|
||||
this.leftArrowHovered = this.isPointInArrow(mouseX, mouseY, this.leftArrowX, this.leftArrowY, this.arrowSize);
|
||||
this.rightArrowHovered = this.isPointInArrow(mouseX, mouseY, this.rightArrowX, this.rightArrowY, this.arrowSize);
|
||||
if (this.currentSlideIndex > 0) {
|
||||
this.renderArrow(graphics, this.leftArrowX, this.leftArrowY, this.arrowSize, true, this.leftArrowScale, this.leftArrowHovered, alpha);
|
||||
}
|
||||
if (this.currentSlideIndex < SLIDES.length - 1) {
|
||||
this.renderArrow(graphics, this.rightArrowX, this.rightArrowY, this.arrowSize, false, this.rightArrowScale, this.rightArrowHovered, alpha);
|
||||
}
|
||||
}
|
||||
|
||||
private void renderArrow(GuiGraphics graphics, int x, int y, int size, boolean pointLeft, float scale, boolean hovered, float alpha) {
|
||||
int scaledSize = (int)((float)size * scale);
|
||||
int offset = (scaledSize - size) / 2;
|
||||
int drawX = x - offset;
|
||||
int drawY = y - offset;
|
||||
int bgColor = hovered ? (int)(alpha * 192.0f) << 24 | 0xF28B0C : (int)(alpha * 128.0f) << 24 | 0x591515;
|
||||
this.fillCircle(graphics, drawX + scaledSize / 2, drawY + scaledSize / 2, scaledSize / 2, bgColor);
|
||||
int arrowColor = (int)(alpha * 255.0f) << 24 | 0xFFFFFF;
|
||||
int centerX = drawX + scaledSize / 2;
|
||||
int centerY = drawY + scaledSize / 2;
|
||||
int arrowWidth = scaledSize / 3;
|
||||
int arrowHeight = scaledSize / 4;
|
||||
if (pointLeft) {
|
||||
this.fillTriangle(graphics, centerX + arrowWidth / 2, centerY - arrowHeight, centerX + arrowWidth / 2, centerY + arrowHeight, centerX - arrowWidth / 2, centerY, arrowColor);
|
||||
} else {
|
||||
this.fillTriangle(graphics, centerX - arrowWidth / 2, centerY - arrowHeight, centerX - arrowWidth / 2, centerY + arrowHeight, centerX + arrowWidth / 2, centerY, arrowColor);
|
||||
}
|
||||
if (hovered) {
|
||||
int glowColor = (int)(alpha * 64.0f) << 24 | 0xF28B0C;
|
||||
this.fillCircle(graphics, drawX + scaledSize / 2, drawY + scaledSize / 2, scaledSize / 2 + 4, glowColor);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isPointInArrow(int px, int py, int arrowX, int arrowY, int size) {
|
||||
int centerX = arrowX + size / 2;
|
||||
int dx = px - centerX;
|
||||
int centerY = arrowY + size / 2;
|
||||
int dy = py - centerY;
|
||||
int radius = size / 2;
|
||||
return dx * dx + dy * dy <= radius * radius;
|
||||
}
|
||||
|
||||
private void fillCircle(GuiGraphics graphics, int centerX, int centerY, int radius, int color) {
|
||||
for (int y = -radius; y <= radius; ++y) {
|
||||
for (int x = -radius; x <= radius; ++x) {
|
||||
if (x * x + y * y > radius * radius) continue;
|
||||
graphics.m_280509_(centerX + x, centerY + y, centerX + x + 1, centerY + y + 1, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void fillTriangle(GuiGraphics graphics, int x1, int y1, int x2, int y2, int x3, int y3, int color) {
|
||||
int minY = Math.min(y1, Math.min(y2, y3));
|
||||
int maxY = Math.max(y1, Math.max(y2, y3));
|
||||
for (int y = minY; y <= maxY; ++y) {
|
||||
int x;
|
||||
int minX = Integer.MAX_VALUE;
|
||||
int maxX = Integer.MIN_VALUE;
|
||||
if (this.checkIntersection(y, y1, y2, x1, x2)) {
|
||||
x = this.interpolate(y, y1, y2, x1, x2);
|
||||
minX = Math.min(minX, x);
|
||||
maxX = Math.max(maxX, x);
|
||||
}
|
||||
if (this.checkIntersection(y, y2, y3, x2, x3)) {
|
||||
x = this.interpolate(y, y2, y3, x2, x3);
|
||||
minX = Math.min(minX, x);
|
||||
maxX = Math.max(maxX, x);
|
||||
}
|
||||
if (this.checkIntersection(y, y3, y1, x3, x1)) {
|
||||
x = this.interpolate(y, y3, y1, x3, x1);
|
||||
minX = Math.min(minX, x);
|
||||
maxX = Math.max(maxX, x);
|
||||
}
|
||||
if (minX == Integer.MAX_VALUE || maxX == Integer.MIN_VALUE) continue;
|
||||
graphics.m_280509_(minX, y, maxX + 1, y + 1, color);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean checkIntersection(int y, int y1, int y2, int x1, int x2) {
|
||||
return y >= Math.min(y1, y2) && y <= Math.max(y1, y2) && y1 != y2;
|
||||
}
|
||||
|
||||
private int interpolate(int y, int y1, int y2, int x1, int x2) {
|
||||
return x1 + (y - y1) * (x2 - x1) / (y2 - y1);
|
||||
}
|
||||
|
||||
public boolean m_6375_(double mouseX, double mouseY, int button) {
|
||||
if (button == 0) {
|
||||
if (this.isPointInButton((int)mouseX, (int)mouseY)) {
|
||||
this.playButtonSound();
|
||||
this.transitionToFirstTimeScreen();
|
||||
return true;
|
||||
}
|
||||
if (this.currentSlideIndex > 0 && this.isPointInArrow((int)mouseX, (int)mouseY, this.leftArrowX, this.leftArrowY, this.arrowSize)) {
|
||||
Integer nextTransition;
|
||||
this.playButtonSound();
|
||||
int targetIndex = this.currentSlideIndex - 1;
|
||||
this.transitionQueue.offer(targetIndex);
|
||||
if (!this.isTransitioning && (nextTransition = this.transitionQueue.poll()) != null) {
|
||||
this.startTransition(nextTransition);
|
||||
}
|
||||
ExplosionOverhaul.LOGGER.info("Queued left arrow transition to {}, queue size: {}", (Object)targetIndex, (Object)this.transitionQueue.size());
|
||||
return true;
|
||||
}
|
||||
if (this.currentSlideIndex < SLIDES.length - 1 && this.isPointInArrow((int)mouseX, (int)mouseY, this.rightArrowX, this.rightArrowY, this.arrowSize)) {
|
||||
Integer nextTransition;
|
||||
this.playButtonSound();
|
||||
int targetIndex = this.currentSlideIndex + 1;
|
||||
this.transitionQueue.offer(targetIndex);
|
||||
if (!this.isTransitioning && (nextTransition = this.transitionQueue.poll()) != null) {
|
||||
this.startTransition(nextTransition);
|
||||
}
|
||||
ExplosionOverhaul.LOGGER.info("Queued right arrow transition to {}, queue size: {}", (Object)targetIndex, (Object)this.transitionQueue.size());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return super.m_6375_(mouseX, mouseY, button);
|
||||
}
|
||||
|
||||
private boolean isPointInButton(int px, int py) {
|
||||
return px >= this.continueButtonX && px <= this.continueButtonX + this.continueButtonWidth && py >= this.continueButtonY && py <= this.continueButtonY + this.continueButtonHeight;
|
||||
}
|
||||
|
||||
private void renderContinueButton(GuiGraphics graphics, int mouseX, int mouseY, float alpha) {
|
||||
this.continueButtonHovered = this.isPointInButton(mouseX, mouseY);
|
||||
int scaledWidth = (int)((float)this.continueButtonWidth * this.continueButtonScale);
|
||||
int scaledHeight = (int)((float)this.continueButtonHeight * this.continueButtonScale);
|
||||
int offsetX = (scaledWidth - this.continueButtonWidth) / 2;
|
||||
int offsetY = (scaledHeight - this.continueButtonHeight) / 2;
|
||||
int drawX = this.continueButtonX - offsetX;
|
||||
int drawY = this.continueButtonY - offsetY;
|
||||
int bgColor = this.continueButtonHovered ? (int)(alpha * 220.0f) << 24 | 0xF28B0C : (int)(alpha * 160.0f) << 24 | 0x591515;
|
||||
graphics.m_280509_(drawX, drawY, drawX + scaledWidth, drawY + scaledHeight, bgColor);
|
||||
if (this.continueButtonHovered) {
|
||||
int glowColor = (int)(alpha * 80.0f) << 24 | 0xF28B0C;
|
||||
int border = 3;
|
||||
graphics.m_280509_(drawX - border, drawY - border, drawX + scaledWidth + border, drawY, glowColor);
|
||||
graphics.m_280509_(drawX - border, drawY + scaledHeight, drawX + scaledWidth + border, drawY + scaledHeight + border, glowColor);
|
||||
graphics.m_280509_(drawX - border, drawY, drawX, drawY + scaledHeight, glowColor);
|
||||
graphics.m_280509_(drawX + scaledWidth, drawY, drawX + scaledWidth + border, drawY + scaledHeight, glowColor);
|
||||
}
|
||||
String text = "Skip Guide";
|
||||
int textColor = (int)(alpha * 255.0f) << 24 | 0xFFFFFF;
|
||||
int textX = drawX + (scaledWidth - this.f_96547_.m_92895_(text)) / 2;
|
||||
Objects.requireNonNull(this.f_96547_);
|
||||
int textY = drawY + (scaledHeight - 9) / 2;
|
||||
graphics.m_280056_(this.f_96547_, text, textX, textY, textColor, true);
|
||||
}
|
||||
|
||||
public boolean m_6913_() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean m_7043_() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void m_7861_() {
|
||||
super.m_7861_();
|
||||
this.transitionQueue.clear();
|
||||
if (this.currentAnimator != null) {
|
||||
this.currentAnimator.close();
|
||||
}
|
||||
if (this.nextAnimator != null) {
|
||||
this.nextAnimator.close();
|
||||
}
|
||||
}
|
||||
|
||||
private void transitionToFirstTimeScreen() {
|
||||
ExplosionOverhaul.LOGGER.info("All guide slides complete. Transitioning to FirstTimeScreen.");
|
||||
Minecraft.m_91087_().m_91152_((Screen)new FirstTimeScreen());
|
||||
}
|
||||
|
||||
private void drawLine(GuiGraphics graphics, int x1, int y1, int x2, int y2, int color) {
|
||||
int dx = Math.abs(x2 - x1);
|
||||
int dy = Math.abs(y2 - y1);
|
||||
int sx = x1 < x2 ? 1 : -1;
|
||||
int sy = y1 < y2 ? 1 : -1;
|
||||
int err = dx - dy;
|
||||
for (int steps = 0; steps < 200; ++steps) {
|
||||
graphics.m_280509_(x1, y1, x1 + 1, y1 + 1, color);
|
||||
if (x1 == x2 && y1 == y2) break;
|
||||
int e2 = 2 * err;
|
||||
if (e2 > -dy) {
|
||||
err -= dy;
|
||||
x1 += sx;
|
||||
}
|
||||
if (e2 >= dx) continue;
|
||||
err += dx;
|
||||
y1 += sy;
|
||||
}
|
||||
}
|
||||
|
||||
private float easeOutCubic(float t) {
|
||||
return 1.0f - (float)Math.pow(1.0f - t, 3.0);
|
||||
}
|
||||
|
||||
private float easeInCubic(float t) {
|
||||
return t * t * t;
|
||||
}
|
||||
|
||||
private float easeInOutCubic(float t) {
|
||||
return t < 0.5f ? 4.0f * t * t * t : 1.0f - (float)Math.pow(-2.0f * t + 2.0f, 3.0) / 2.0f;
|
||||
}
|
||||
|
||||
private void playButtonSound() {
|
||||
try {
|
||||
Minecraft minecraft = Minecraft.m_91087_();
|
||||
if (minecraft.m_91106_() != null) {
|
||||
minecraft.m_91106_().m_120367_((SoundInstance)SimpleSoundInstance.m_119755_((SoundEvent)((SoundEvent)ModSounds.BUTTON_SOUND.get()), (float)1.0f, (float)1.0f));
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
ExplosionOverhaul.LOGGER.warn("Failed to play button sound", (Throwable)e);
|
||||
}
|
||||
}
|
||||
|
||||
private static class SlideData {
|
||||
final ResourceLocation spriteSheet;
|
||||
final int totalFrames;
|
||||
final String guideText;
|
||||
|
||||
SlideData(String filename, int frames, String text) {
|
||||
this.spriteSheet = ResourceLocation.fromNamespaceAndPath((String)"explosionoverhaul", (String)("intro_gui/" + filename));
|
||||
this.totalFrames = frames;
|
||||
this.guideText = text;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul.client;
|
||||
|
||||
import com.vinlanx.explosionoverhaul.ExplosionOverhaul;
|
||||
import com.vinlanx.explosionoverhaul.ModSounds;
|
||||
import com.vinlanx.explosionoverhaul.client.FadingMusicInstance;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.resources.sounds.SimpleSoundInstance;
|
||||
import net.minecraft.client.resources.sounds.SoundInstance;
|
||||
import net.minecraft.client.sounds.SoundManager;
|
||||
import net.minecraft.sounds.SoundEvent;
|
||||
import net.minecraft.sounds.SoundSource;
|
||||
|
||||
public class IntroMusicManager {
|
||||
private static IntroMusicManager INSTANCE;
|
||||
private static final float FADE_OUT_DURATION = 3.0f;
|
||||
private FadingMusicInstance musicInstance;
|
||||
private SimpleSoundInstance boomInstance;
|
||||
private boolean isPlaying = false;
|
||||
private boolean isFadingOut = false;
|
||||
private boolean vanillaMusicBlocked = false;
|
||||
|
||||
private IntroMusicManager() {
|
||||
}
|
||||
|
||||
public static IntroMusicManager getInstance() {
|
||||
if (INSTANCE == null) {
|
||||
INSTANCE = new IntroMusicManager();
|
||||
}
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
public void start() {
|
||||
if (this.isPlaying) {
|
||||
return;
|
||||
}
|
||||
SoundManager soundManager = Minecraft.m_91087_().m_91106_();
|
||||
this.musicInstance = new FadingMusicInstance((SoundEvent)ModSounds.INTRO_MUSIC.get(), 0.25f, SoundSource.MASTER);
|
||||
soundManager.m_120367_((SoundInstance)this.musicInstance);
|
||||
ExplosionOverhaul.LOGGER.info("Started intro music with FadingMusicInstance");
|
||||
this.boomInstance = SimpleSoundInstance.m_119755_((SoundEvent)((SoundEvent)ModSounds.INTRO_BOOM.get()), (float)1.0f, (float)1.0f);
|
||||
soundManager.m_120367_((SoundInstance)this.boomInstance);
|
||||
this.isPlaying = true;
|
||||
this.vanillaMusicBlocked = true;
|
||||
this.stopVanillaMusic();
|
||||
}
|
||||
|
||||
public void startFadeOut() {
|
||||
ExplosionOverhaul.LOGGER.info("startFadeOut called. isPlaying={}, isFadingOut={}", (Object)this.isPlaying, (Object)this.isFadingOut);
|
||||
if (!this.isPlaying || this.isFadingOut) {
|
||||
ExplosionOverhaul.LOGGER.warn("Cannot start fade out - already fading or not playing");
|
||||
return;
|
||||
}
|
||||
if (this.musicInstance != null) {
|
||||
this.musicInstance.fadeOutAndStop(3.0f);
|
||||
ExplosionOverhaul.LOGGER.info("Started smooth fade out over {} seconds", (Object)Float.valueOf(3.0f));
|
||||
}
|
||||
this.isFadingOut = true;
|
||||
}
|
||||
|
||||
public void stopBoomSound() {
|
||||
if (this.boomInstance != null) {
|
||||
try {
|
||||
SoundManager soundManager = Minecraft.m_91087_().m_91106_();
|
||||
soundManager.m_120399_((SoundInstance)this.boomInstance);
|
||||
this.boomInstance = null;
|
||||
ExplosionOverhaul.LOGGER.info("Boom sound stopped.");
|
||||
}
|
||||
catch (Exception e) {
|
||||
ExplosionOverhaul.LOGGER.warn("Failed to stop boom sound: {}", (Object)e.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
ExplosionOverhaul.LOGGER.info("stop() called! Stack trace:", (Throwable)new Exception("Music stop trace"));
|
||||
SoundManager soundManager = Minecraft.m_91087_().m_91106_();
|
||||
if (this.musicInstance != null) {
|
||||
soundManager.m_120399_((SoundInstance)this.musicInstance);
|
||||
this.musicInstance = null;
|
||||
}
|
||||
if (this.boomInstance != null) {
|
||||
soundManager.m_120399_((SoundInstance)this.boomInstance);
|
||||
this.boomInstance = null;
|
||||
}
|
||||
this.isPlaying = false;
|
||||
this.isFadingOut = false;
|
||||
this.vanillaMusicBlocked = false;
|
||||
ExplosionOverhaul.LOGGER.info("Music stopped completely.");
|
||||
}
|
||||
|
||||
public void tick(float deltaTime) {
|
||||
if (!this.isPlaying) {
|
||||
return;
|
||||
}
|
||||
if (this.isFadingOut && this.musicInstance != null) {
|
||||
if (this.musicInstance.hasFinishedFading()) {
|
||||
ExplosionOverhaul.LOGGER.info("Music fade out complete!");
|
||||
this.stop();
|
||||
return;
|
||||
}
|
||||
float currentVolume = this.musicInstance.getCurrentVolume();
|
||||
if (currentVolume % 0.1f < 0.05f) {
|
||||
ExplosionOverhaul.LOGGER.info("Fade out progress - volume: {}", (Object)Float.valueOf(currentVolume));
|
||||
}
|
||||
}
|
||||
if (this.vanillaMusicBlocked) {
|
||||
this.stopVanillaMusic();
|
||||
}
|
||||
}
|
||||
|
||||
private void stopVanillaMusic() {
|
||||
Minecraft mc = Minecraft.m_91087_();
|
||||
if (mc.m_91397_() != null) {
|
||||
mc.m_91397_().m_120186_();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isPlaying() {
|
||||
return this.isPlaying;
|
||||
}
|
||||
|
||||
public boolean isFadingOut() {
|
||||
return this.isFadingOut;
|
||||
}
|
||||
|
||||
public boolean isVanillaMusicBlocked() {
|
||||
return this.vanillaMusicBlocked;
|
||||
}
|
||||
|
||||
public float getFadeProgress() {
|
||||
if (!this.isFadingOut || this.musicInstance == null) {
|
||||
return 0.0f;
|
||||
}
|
||||
return 1.0f - this.musicInstance.getCurrentVolume();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul.client;
|
||||
|
||||
import com.vinlanx.explosionoverhaul.client.IntroMusicManager;
|
||||
import net.neoforged.api.distmarker.Dist;
|
||||
import net.neoforged.neoforge.event.TickEvent;
|
||||
import net.neoforged.bus.api.SubscribeEvent;
|
||||
import net.neoforged.fml.common.Mod;
|
||||
|
||||
@Mod.EventBusSubscriber(modid="explosionoverhaul", bus=Mod.EventBusSubscriber.Bus.FORGE, value={Dist.CLIENT})
|
||||
public class IntroMusicTickHandler {
|
||||
private static long lastTickTime = System.currentTimeMillis();
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onClientTick(TickEvent.ClientTickEvent event) {
|
||||
if (event.phase != TickEvent.Phase.END) {
|
||||
return;
|
||||
}
|
||||
IntroMusicManager musicManager = IntroMusicManager.getInstance();
|
||||
if (musicManager.isPlaying() || musicManager.isFadingOut()) {
|
||||
long currentTime = System.currentTimeMillis();
|
||||
float deltaTime = (float)(currentTime - lastTickTime) / 1000.0f;
|
||||
lastTickTime = currentTime;
|
||||
musicManager.tick(deltaTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul.client;
|
||||
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.vinlanx.explosionoverhaul.client.IntroMusicManager;
|
||||
import com.vinlanx.explosionoverhaul.client.SpriteSheetAnimator;
|
||||
import com.vinlanx.explosionoverhaul.client.VinlanxSplashScreen;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiGraphics;
|
||||
import net.minecraft.client.gui.screens.Screen;
|
||||
import net.minecraft.client.gui.screens.TitleScreen;
|
||||
import net.minecraft.client.renderer.GameRenderer;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
public class IntroSplashScreen
|
||||
extends Screen {
|
||||
private static final ResourceLocation SPRITE_SHEET = ResourceLocation.fromNamespaceAndPath((String)"explosionoverhaul", (String)"intro_gui/screen.png");
|
||||
private static final int FRAME_WIDTH = 1280;
|
||||
private static final int FRAME_HEIGHT = 720;
|
||||
private static final int COLUMNS = 14;
|
||||
private static final int ROWS = 14;
|
||||
private static final int TOTAL_FRAMES = 196;
|
||||
private static final int FPS = 24;
|
||||
private SpriteSheetAnimator animator;
|
||||
private IntroMusicManager musicManager;
|
||||
private long lastFrameTime = System.currentTimeMillis();
|
||||
private boolean animationFinished = false;
|
||||
|
||||
public IntroSplashScreen() {
|
||||
super((Component)Component.m_237113_((String)"Intro"));
|
||||
}
|
||||
|
||||
protected void m_7856_() {
|
||||
super.m_7856_();
|
||||
this.animator = new SpriteSheetAnimator(SPRITE_SHEET, 1280, 720, 14, 14, 196, 24);
|
||||
this.animator.load();
|
||||
this.animator.play();
|
||||
this.musicManager = IntroMusicManager.getInstance();
|
||||
this.musicManager.start();
|
||||
}
|
||||
|
||||
public void m_86600_() {
|
||||
super.m_86600_();
|
||||
long currentTime = System.currentTimeMillis();
|
||||
float deltaTime = (float)(currentTime - this.lastFrameTime) / 1000.0f;
|
||||
this.lastFrameTime = currentTime;
|
||||
if (this.animator != null) {
|
||||
this.animator.tick(deltaTime);
|
||||
if (this.animator.getCurrentFrame() >= 195 && !this.animationFinished) {
|
||||
this.animationFinished = true;
|
||||
this.transitionToFirstTimeScreen();
|
||||
}
|
||||
}
|
||||
if (this.musicManager != null) {
|
||||
this.musicManager.tick(deltaTime);
|
||||
}
|
||||
}
|
||||
|
||||
public void m_88315_(GuiGraphics graphics, int mouseX, int mouseY, float partialTick) {
|
||||
int displayWidth;
|
||||
int displayHeight;
|
||||
graphics.m_280509_(0, 0, this.f_96543_, this.f_96544_, -16777216);
|
||||
if (this.animator == null) {
|
||||
return;
|
||||
}
|
||||
ResourceLocation texture = this.animator.getTextureLocation();
|
||||
if (texture == null) {
|
||||
return;
|
||||
}
|
||||
float screenAspectRatio = (float)this.f_96543_ / (float)this.f_96544_;
|
||||
float targetAspectRatio = 1.7777778f;
|
||||
if (screenAspectRatio > targetAspectRatio) {
|
||||
displayHeight = this.f_96544_;
|
||||
displayWidth = (int)((float)displayHeight * targetAspectRatio);
|
||||
} else {
|
||||
displayWidth = this.f_96543_;
|
||||
displayHeight = (int)((float)displayWidth / targetAspectRatio);
|
||||
}
|
||||
int x = (this.f_96543_ - displayWidth) / 2;
|
||||
int y = (this.f_96544_ - displayHeight) / 2;
|
||||
RenderSystem.setShader(GameRenderer::m_172817_);
|
||||
RenderSystem.setShaderTexture((int)0, (ResourceLocation)texture);
|
||||
RenderSystem.setShaderColor((float)1.0f, (float)1.0f, (float)1.0f, (float)1.0f);
|
||||
RenderSystem.enableBlend();
|
||||
RenderSystem.defaultBlendFunc();
|
||||
graphics.m_280411_(texture, x, y, displayWidth, displayHeight, 0.0f, 0.0f, 1280, 720, 1280, 720);
|
||||
RenderSystem.disableBlend();
|
||||
}
|
||||
|
||||
public boolean m_6913_() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean m_7933_(int keyCode, int scanCode, int modifiers) {
|
||||
if (keyCode == 256) {
|
||||
this.skipToNext();
|
||||
return true;
|
||||
}
|
||||
return super.m_7933_(keyCode, scanCode, modifiers);
|
||||
}
|
||||
|
||||
public boolean m_6375_(double mouseX, double mouseY, int button) {
|
||||
this.skipToNext();
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean m_7043_() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void m_7861_() {
|
||||
super.m_7861_();
|
||||
if (this.animator != null) {
|
||||
this.animator.close();
|
||||
}
|
||||
if (this.musicManager != null) {
|
||||
this.musicManager.stopBoomSound();
|
||||
}
|
||||
}
|
||||
|
||||
private void skipToNext() {
|
||||
this.animationFinished = true;
|
||||
this.transitionToFirstTimeScreen();
|
||||
}
|
||||
|
||||
private void transitionToFirstTimeScreen() {
|
||||
Minecraft mc = Minecraft.m_91087_();
|
||||
if (!(mc.f_91080_ instanceof TitleScreen)) {
|
||||
mc.execute(() -> {
|
||||
if (mc.f_91080_ instanceof TitleScreen) {
|
||||
mc.m_91152_((Screen)new VinlanxSplashScreen());
|
||||
} else {
|
||||
mc.m_91152_((Screen)new VinlanxSplashScreen());
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
mc.m_91152_((Screen)new VinlanxSplashScreen());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul.client;
|
||||
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||
import net.minecraft.client.Camera;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.client.particle.ParticleRenderType;
|
||||
import net.minecraft.client.particle.SpriteSet;
|
||||
import net.minecraft.client.particle.TextureSheetParticle;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.joml.Vector3f;
|
||||
import org.joml.Vector3fc;
|
||||
|
||||
public class LineSparkParticle
|
||||
extends TextureSheetParticle {
|
||||
private final SpriteSet spriteSet;
|
||||
private float length;
|
||||
private float width;
|
||||
private final float initialLength;
|
||||
private static final Vec3 UP = new Vec3(0.0, 1.0, 0.0);
|
||||
|
||||
public LineSparkParticle(ClientLevel pLevel, double pX, double pY, double pZ, double pXSpeed, double pYSpeed, double pZSpeed, SpriteSet pSpriteSet) {
|
||||
super(pLevel, pX, pY, pZ, pXSpeed, pYSpeed, pZSpeed);
|
||||
float baseSize;
|
||||
this.f_107215_ = pXSpeed;
|
||||
this.f_107216_ = pYSpeed;
|
||||
this.f_107217_ = pZSpeed;
|
||||
this.spriteSet = pSpriteSet;
|
||||
this.f_172258_ = 0.97f;
|
||||
this.f_107226_ = 0.4f;
|
||||
this.f_107225_ = 250 + this.f_107223_.m_188503_(150);
|
||||
this.initialLength = baseSize = (this.f_107223_.m_188501_() * 0.4f + 0.5f) * 1.2f;
|
||||
this.length = 0.1f;
|
||||
this.width = baseSize * 0.125f;
|
||||
this.m_108337_(this.spriteSet.m_5819_(0, 1));
|
||||
}
|
||||
|
||||
public void m_5989_() {
|
||||
float stretchFactor;
|
||||
super.m_5989_();
|
||||
float lifeProgress = (float)this.f_107224_ / (float)this.f_107225_;
|
||||
if (lifeProgress < 0.2f) {
|
||||
t = lifeProgress / 0.2f;
|
||||
stretchFactor = 1.0f - (1.0f - t) * (1.0f - t);
|
||||
} else if (lifeProgress < 0.7f) {
|
||||
stretchFactor = 1.0f;
|
||||
} else {
|
||||
t = (lifeProgress - 0.7f) / 0.3f;
|
||||
stretchFactor = 1.0f - t * t;
|
||||
}
|
||||
stretchFactor = Mth.m_14036_((float)stretchFactor, (float)0.0f, (float)1.0f);
|
||||
float distanceScale = 1.0f;
|
||||
Minecraft mc = Minecraft.m_91087_();
|
||||
if (mc.f_91074_ != null) {
|
||||
double distSqr = mc.f_91074_.m_20275_(this.f_107212_, this.f_107213_, this.f_107214_);
|
||||
double dist = Math.sqrt(distSqr);
|
||||
if (dist > 171.0) {
|
||||
distanceScale = 2.5f;
|
||||
} else if (dist > 141.0) {
|
||||
distanceScale = 2.2f;
|
||||
} else if (dist > 101.0) {
|
||||
distanceScale = 2.0f;
|
||||
} else if (dist > 71.0) {
|
||||
distanceScale = 1.7f;
|
||||
} else if (dist > 50.0) {
|
||||
distanceScale = 1.5f;
|
||||
}
|
||||
}
|
||||
this.length = this.initialLength * stretchFactor * distanceScale;
|
||||
this.width = this.initialLength * 0.125f * distanceScale;
|
||||
if (this.length < 0.01f) {
|
||||
this.length = 0.01f;
|
||||
}
|
||||
this.f_107230_ = Mth.m_14089_((float)((float)this.f_107224_ / (float)this.f_107225_ * (float)Math.PI / 2.0f));
|
||||
if (this.f_107218_) {
|
||||
this.m_107274_();
|
||||
}
|
||||
}
|
||||
|
||||
public ParticleRenderType m_7556_() {
|
||||
return ParticleRenderType.f_107431_;
|
||||
}
|
||||
|
||||
public void m_5744_(VertexConsumer buffer, Camera camera, float partialTicks) {
|
||||
Vec3 camPos = camera.m_90583_();
|
||||
float x = (float)(Mth.m_14139_((double)partialTicks, (double)this.f_107209_, (double)this.f_107212_) - camPos.m_7096_());
|
||||
float y = (float)(Mth.m_14139_((double)partialTicks, (double)this.f_107210_, (double)this.f_107213_) - camPos.m_7098_());
|
||||
float z = (float)(Mth.m_14139_((double)partialTicks, (double)this.f_107211_, (double)this.f_107214_) - camPos.m_7094_());
|
||||
Vec3 velocity = new Vec3(this.f_107215_, this.f_107216_, this.f_107217_).m_82541_();
|
||||
if (velocity.m_82556_() < 1.0E-4) {
|
||||
return;
|
||||
}
|
||||
Vec3 viewVector = new Vec3((double)x, (double)y, (double)z).m_82541_();
|
||||
Vec3 rightVector = velocity.m_82537_(viewVector).m_82541_();
|
||||
if (rightVector.m_82556_() < 1.0E-4 && (rightVector = velocity.m_82537_(UP).m_82541_()).m_82556_() < 1.0E-4) {
|
||||
rightVector = velocity.m_82537_(new Vec3(1.0, 0.0, 0.0)).m_82541_();
|
||||
}
|
||||
Vec3 upVector = rightVector.m_82537_(velocity).m_82541_();
|
||||
Vector3f[] vertices = new Vector3f[]{new Vector3f(x, y, z).add((Vector3fc)upVector.m_82490_((double)(-this.length / 2.0f)).m_82549_(rightVector.m_82490_((double)(this.width / 2.0f))).m_252839_()), new Vector3f(x, y, z).add((Vector3fc)upVector.m_82490_((double)(this.length / 2.0f)).m_82549_(rightVector.m_82490_((double)(this.width / 2.0f))).m_252839_()), new Vector3f(x, y, z).add((Vector3fc)upVector.m_82490_((double)(this.length / 2.0f)).m_82549_(rightVector.m_82490_((double)(-this.width / 2.0f))).m_252839_()), new Vector3f(x, y, z).add((Vector3fc)upVector.m_82490_((double)(-this.length / 2.0f)).m_82549_(rightVector.m_82490_((double)(-this.width / 2.0f))).m_252839_())};
|
||||
int worldLight = this.m_6355_(partialTicks);
|
||||
this.renderQuad(buffer, vertices, this.f_108321_, this.f_107227_, this.f_107228_, this.f_107229_, this.f_107230_, worldLight);
|
||||
TextureAtlasSprite emissiveSprite = this.spriteSet.m_5819_(1, 1);
|
||||
int fullBright = 240;
|
||||
this.renderQuad(buffer, vertices, emissiveSprite, 1.0f, 1.0f, 1.0f, this.f_107230_, fullBright);
|
||||
}
|
||||
|
||||
private void renderQuad(VertexConsumer buffer, Vector3f[] vertices, TextureAtlasSprite sprite, float r, float g, float b, float a, int light) {
|
||||
float u0 = sprite.m_118409_();
|
||||
float u1 = sprite.m_118410_();
|
||||
float v0 = sprite.m_118411_();
|
||||
float v1 = sprite.m_118412_();
|
||||
buffer.m_5483_((double)vertices[0].x(), (double)vertices[0].y(), (double)vertices[0].z()).m_7421_(u1, v1).m_85950_(r, g, b, a).m_85969_(light).m_5752_();
|
||||
buffer.m_5483_((double)vertices[1].x(), (double)vertices[1].y(), (double)vertices[1].z()).m_7421_(u1, v0).m_85950_(r, g, b, a).m_85969_(light).m_5752_();
|
||||
buffer.m_5483_((double)vertices[2].x(), (double)vertices[2].y(), (double)vertices[2].z()).m_7421_(u0, v0).m_85950_(r, g, b, a).m_85969_(light).m_5752_();
|
||||
buffer.m_5483_((double)vertices[3].x(), (double)vertices[3].y(), (double)vertices[3].z()).m_7421_(u0, v1).m_85950_(r, g, b, a).m_85969_(light).m_5752_();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul.client;
|
||||
|
||||
import com.vinlanx.explosionoverhaul.client.LineSparkParticle;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.client.particle.Particle;
|
||||
import net.minecraft.client.particle.ParticleProvider;
|
||||
import net.minecraft.client.particle.SpriteSet;
|
||||
import net.minecraft.core.particles.SimpleParticleType;
|
||||
|
||||
public class LineSparkParticleProvider
|
||||
implements ParticleProvider<SimpleParticleType> {
|
||||
private final SpriteSet spriteSet;
|
||||
|
||||
public LineSparkParticleProvider(SpriteSet pSprites) {
|
||||
this.spriteSet = pSprites;
|
||||
}
|
||||
|
||||
public Particle createParticle(SimpleParticleType pType, ClientLevel pLevel, double pX, double pY, double pZ, double pXSpeed, double pYSpeed, double pZSpeed) {
|
||||
return new LineSparkParticle(pLevel, pX, pY, pZ, pXSpeed, pYSpeed, pZSpeed, this.spriteSet);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,310 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul.client;
|
||||
|
||||
import com.vinlanx.explosionoverhaul.Config;
|
||||
import com.vinlanx.explosionoverhaul.client.SoundEngineAudioQueue;
|
||||
import com.vinlanx.explosionoverhaul.client.SoundPhysicsCompatibility;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.neoforged.api.distmarker.Dist;
|
||||
import net.neoforged.api.distmarker.OnlyIn;
|
||||
import net.neoforged.neoforge.event.TickEvent;
|
||||
import net.neoforged.bus.api.SubscribeEvent;
|
||||
import net.neoforged.fml.common.Mod;
|
||||
import org.lwjgl.openal.AL10;
|
||||
import org.lwjgl.openal.ALC10;
|
||||
import org.lwjgl.openal.EXTEfx;
|
||||
|
||||
@OnlyIn(value=Dist.CLIENT)
|
||||
@Mod.EventBusSubscriber(modid="explosionoverhaul", value={Dist.CLIENT})
|
||||
public class LowPassConcussionEffect {
|
||||
private static final float HF_MIN = 0.01f;
|
||||
private static final float HF_MAX = 1.0f;
|
||||
private static final float GAIN_MIN = 0.1f;
|
||||
private static final int FADE_IN_TICKS = 40;
|
||||
private static final int FADE_OUT_TICKS = 100;
|
||||
private static volatile Phase phase = Phase.IDLE;
|
||||
private static volatile int holdTicks = 0;
|
||||
private static volatile int ticksInPhase = 0;
|
||||
private static final AtomicBoolean efxAvailable = new AtomicBoolean(false);
|
||||
private static volatile int filterId = 0;
|
||||
private static volatile float targetHfMin = 1.0f;
|
||||
private static volatile float targetGainMin = 1.0f;
|
||||
private static volatile float currentDeafnessGain = 1.0f;
|
||||
public static volatile boolean enabled = true;
|
||||
public static volatile boolean debugShowChat = false;
|
||||
private static volatile boolean compatibilityMode = false;
|
||||
private static volatile float lastAppliedHf = 1.0f;
|
||||
private static volatile float lastAppliedGain = 1.0f;
|
||||
|
||||
public static void setDeafnessGain(float gain) {
|
||||
currentDeafnessGain = Math.max(0.0f, Math.min(1.0f, gain));
|
||||
if (phase == Phase.IDLE && currentDeafnessGain < 0.99f && !compatibilityMode) {
|
||||
SoundEngineAudioQueue.enqueueAudio(() -> LowPassConcussionEffect.ensureFilterExists());
|
||||
}
|
||||
}
|
||||
|
||||
private static void ensureFilterExists() {
|
||||
if (!efxAvailable.get()) {
|
||||
long ctx = ALC10.alcGetCurrentContext();
|
||||
long dev = ALC10.alcGetContextsDevice((long)ctx);
|
||||
if (!ALC10.alcIsExtensionPresent((long)dev, (CharSequence)"ALC_EXT_EFX")) {
|
||||
efxAvailable.set(false);
|
||||
return;
|
||||
}
|
||||
efxAvailable.set(true);
|
||||
}
|
||||
if (filterId == 0) {
|
||||
filterId = EXTEfx.alGenFilters();
|
||||
EXTEfx.alFilteri((int)filterId, (int)32769, (int)1);
|
||||
EXTEfx.alFilterf((int)filterId, (int)1, (float)1.0f);
|
||||
EXTEfx.alFilterf((int)filterId, (int)2, (float)1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
public static void start(int seconds, float intensity) {
|
||||
Minecraft mc;
|
||||
if (!enabled) {
|
||||
return;
|
||||
}
|
||||
if (seconds < 1) {
|
||||
seconds = 1;
|
||||
}
|
||||
if (seconds > 600) {
|
||||
seconds = 600;
|
||||
}
|
||||
float effectiveIntensity = (Boolean)Config.CLIENT.enableLowPass.get() != false ? intensity : 0.001f;
|
||||
float addedStrength = Math.max(0.0f, Math.min(1.0f, effectiveIntensity));
|
||||
if (phase != Phase.IDLE) {
|
||||
float currentStrength = (1.0f - targetHfMin) / 0.99f;
|
||||
float totalStrength = Math.min(1.0f, currentStrength + addedStrength);
|
||||
targetHfMin = 1.0f - totalStrength * 0.99f;
|
||||
holdTicks = Math.min(2000, holdTicks + seconds * 20);
|
||||
if (phase == Phase.FADE_OUT) {
|
||||
phase = Phase.HOLD;
|
||||
ticksInPhase = 0;
|
||||
}
|
||||
} else {
|
||||
float totalStrength = addedStrength;
|
||||
targetHfMin = 1.0f - totalStrength * 0.99f;
|
||||
targetGainMin = 0.1f;
|
||||
holdTicks = seconds * 20;
|
||||
ticksInPhase = 0;
|
||||
phase = Phase.FADE_IN;
|
||||
}
|
||||
if (!compatibilityMode) {
|
||||
SoundEngineAudioQueue.enqueueAudio(() -> {
|
||||
try {
|
||||
LowPassConcussionEffect.ensureFilterExists();
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
efxAvailable.set(false);
|
||||
}
|
||||
});
|
||||
SoundEngineAudioQueue.drainNow();
|
||||
}
|
||||
if (debugShowChat && (mc = Minecraft.m_91087_()) != null && mc.f_91074_ != null) {
|
||||
mc.f_91074_.m_5661_((Component)Component.m_237113_((String)("Low pass test queued for " + seconds + "s (strength=" + addedStrength + ")")), false);
|
||||
}
|
||||
}
|
||||
|
||||
public static void start(int seconds, float intensity, double effectivePercent, String visibility, int intensityPercent) {
|
||||
Minecraft mc;
|
||||
if (debugShowChat && (mc = Minecraft.m_91087_()) != null && mc.f_91074_ != null) {
|
||||
mc.f_91074_.m_5661_((Component)Component.m_237113_((String)"__________________________________________"), false);
|
||||
String msg = String.format("\u041f\u043e\u0442\u0443\u0436\u043d\u0456\u0441\u0442\u044c \u043a\u043e\u043d\u0442\u0443\u0437\u0456\u0457 %.1f%% (%s) \u2014 \u0421\u0438\u043b\u0430 \u043f\u0440\u0438\u0433\u043b\u0443\u0448\u0435\u043d\u043d\u044f %d%%, \u0427\u0430\u0441 \u043f\u0440\u0438\u0433\u043b\u0443\u0448\u0435\u043d\u043d\u044f %.1f \u0441\u0435\u043a", effectivePercent, visibility, intensityPercent, (double)seconds);
|
||||
mc.f_91074_.m_5661_((Component)Component.m_237113_((String)msg).m_130940_(ChatFormatting.WHITE), false);
|
||||
mc.f_91074_.m_5661_((Component)Component.m_237113_((String)"__________________________________________"), false);
|
||||
}
|
||||
LowPassConcussionEffect.start(seconds, intensity);
|
||||
}
|
||||
|
||||
public static void stop() {
|
||||
phase = Phase.IDLE;
|
||||
ticksInPhase = 0;
|
||||
lastAppliedHf = 1.0f;
|
||||
lastAppliedGain = 1.0f;
|
||||
targetGainMin = 1.0f;
|
||||
if (compatibilityMode) {
|
||||
SoundEngineAudioQueue.enqueueAudio(SoundPhysicsCompatibility::reapplyDirectFilterParameters);
|
||||
}
|
||||
SoundEngineAudioQueue.enqueueAudio(() -> {
|
||||
if (filterId != 0) {
|
||||
try {
|
||||
EXTEfx.alFilterf((int)filterId, (int)2, (float)1.0f);
|
||||
EXTEfx.alFilterf((int)filterId, (int)1, (float)1.0f);
|
||||
}
|
||||
catch (Throwable throwable) {
|
||||
// empty catch block
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static boolean isActive() {
|
||||
return phase != Phase.IDLE || currentDeafnessGain < 0.99f;
|
||||
}
|
||||
|
||||
public static int getFilterId() {
|
||||
return filterId;
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onClientTick(TickEvent.ClientTickEvent event) {
|
||||
if (event.phase == TickEvent.Phase.END) {
|
||||
LowPassConcussionEffect.onClientTick();
|
||||
}
|
||||
}
|
||||
|
||||
public static void onClientTick() {
|
||||
Minecraft mc = Minecraft.m_91087_();
|
||||
if (mc != null && mc.m_91104_()) {
|
||||
return;
|
||||
}
|
||||
if (currentDeafnessGain < 0.99f || phase != Phase.IDLE) {
|
||||
float hf = 1.0f;
|
||||
float gainInterp = 1.0f;
|
||||
if (phase != Phase.IDLE) {
|
||||
++ticksInPhase;
|
||||
switch (phase) {
|
||||
case FADE_IN: {
|
||||
float t = Math.min(1.0f, (float)ticksInPhase / 40.0f);
|
||||
hf = LowPassConcussionEffect.lerp(1.0f, targetHfMin, LowPassConcussionEffect.easeOutQuad(t));
|
||||
gainInterp = LowPassConcussionEffect.lerp(1.0f, targetGainMin, LowPassConcussionEffect.easeOutQuad(t));
|
||||
if (ticksInPhase < 40) break;
|
||||
phase = Phase.HOLD;
|
||||
ticksInPhase = 0;
|
||||
hf = targetHfMin;
|
||||
gainInterp = targetGainMin;
|
||||
break;
|
||||
}
|
||||
case HOLD: {
|
||||
hf = targetHfMin;
|
||||
gainInterp = targetGainMin;
|
||||
if (ticksInPhase < holdTicks) break;
|
||||
phase = Phase.FADE_OUT;
|
||||
ticksInPhase = 0;
|
||||
break;
|
||||
}
|
||||
case FADE_OUT: {
|
||||
float t = Math.min(1.0f, (float)ticksInPhase / 100.0f);
|
||||
hf = LowPassConcussionEffect.lerp(targetHfMin, 1.0f, LowPassConcussionEffect.easeInQuad(t));
|
||||
gainInterp = LowPassConcussionEffect.lerp(targetGainMin, 1.0f, LowPassConcussionEffect.easeInQuad(t));
|
||||
if (ticksInPhase < 100) break;
|
||||
LowPassConcussionEffect.stop();
|
||||
hf = 1.0f;
|
||||
gainInterp = 1.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
float combinedGain = Math.max(0.0f, Math.min(1.0f, gainInterp * currentDeafnessGain));
|
||||
LowPassConcussionEffect.applyFilterParamsOnAudioThread(hf, combinedGain);
|
||||
}
|
||||
}
|
||||
|
||||
private static void applyFilterParamsOnAudioThread(float hf, float gain) {
|
||||
float clampedHf = Math.max(0.01f, Math.min(1.0f, hf));
|
||||
float clampedGain = Math.max(0.0f, Math.min(1.0f, gain));
|
||||
lastAppliedHf = clampedHf;
|
||||
lastAppliedGain = clampedGain;
|
||||
if (compatibilityMode) {
|
||||
SoundEngineAudioQueue.enqueueAudio(SoundPhysicsCompatibility::reapplyDirectFilterParameters);
|
||||
}
|
||||
if (!efxAvailable.get()) {
|
||||
return;
|
||||
}
|
||||
int fid = filterId;
|
||||
if (fid == 0) {
|
||||
return;
|
||||
}
|
||||
SoundEngineAudioQueue.enqueueAudio(() -> {
|
||||
try {
|
||||
EXTEfx.alFilterf((int)fid, (int)2, (float)clampedHf);
|
||||
EXTEfx.alFilterf((int)fid, (int)1, (float)clampedGain);
|
||||
}
|
||||
catch (Throwable throwable) {
|
||||
// empty catch block
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static float lerp(float a, float b, float t) {
|
||||
return a + (b - a) * t;
|
||||
}
|
||||
|
||||
private static float easeOutQuad(float t) {
|
||||
return 1.0f - (1.0f - t) * (1.0f - t);
|
||||
}
|
||||
|
||||
private static float easeInQuad(float t) {
|
||||
return t * t;
|
||||
}
|
||||
|
||||
private static String alErrorName(int err) {
|
||||
return switch (err) {
|
||||
case 0 -> "AL_NO_ERROR";
|
||||
case 40961 -> "AL_INVALID_NAME";
|
||||
case 40962 -> "AL_INVALID_ENUM";
|
||||
case 40963 -> "AL_INVALID_VALUE";
|
||||
case 40964 -> "AL_INVALID_OPERATION";
|
||||
case 40965 -> "AL_OUT_OF_MEMORY";
|
||||
default -> "AL_UNKNOWN_ERROR";
|
||||
};
|
||||
}
|
||||
|
||||
public static void setCompatibilityMode(boolean compatibilityActive) {
|
||||
compatibilityMode = compatibilityActive;
|
||||
}
|
||||
|
||||
public static float getCurrentHfMultiplier() {
|
||||
return Math.max(0.01f, Math.min(1.0f, lastAppliedHf));
|
||||
}
|
||||
|
||||
public static float getCurrentGainMultiplier() {
|
||||
return Math.max(0.0f, Math.min(1.0f, lastAppliedGain));
|
||||
}
|
||||
|
||||
public static void attachFilterToSource(int sourceId) {
|
||||
if (sourceId <= 0) {
|
||||
return;
|
||||
}
|
||||
if (!efxAvailable.get() || filterId == 0) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
if (!AL10.alIsSource((int)sourceId)) {
|
||||
return;
|
||||
}
|
||||
if (AL10.alGetSourcei((int)sourceId, (int)514) == 1) {
|
||||
return;
|
||||
}
|
||||
AL10.alSourcei((int)sourceId, (int)131077, (int)filterId);
|
||||
}
|
||||
catch (Throwable throwable) {
|
||||
// empty catch block
|
||||
}
|
||||
}
|
||||
|
||||
public static void detachFilterFromSource(int sourceId) {
|
||||
try {
|
||||
if (AL10.alIsSource((int)sourceId)) {
|
||||
AL10.alSourcei((int)sourceId, (int)131077, (int)0);
|
||||
}
|
||||
}
|
||||
catch (Throwable throwable) {
|
||||
// empty catch block
|
||||
}
|
||||
}
|
||||
|
||||
private static enum Phase {
|
||||
IDLE,
|
||||
FADE_IN,
|
||||
HOLD,
|
||||
FADE_OUT;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,256 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul.client;
|
||||
|
||||
import com.vinlanx.explosionoverhaul.Config;
|
||||
import com.vinlanx.explosionoverhaul.CraterDeformer;
|
||||
import com.vinlanx.explosionoverhaul.client.BlacklistScreen;
|
||||
import com.vinlanx.explosionoverhaul.client.ExplosionTextureManager;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import me.shedaniel.clothconfig2.api.AbstractConfigListEntry;
|
||||
import me.shedaniel.clothconfig2.api.ConfigBuilder;
|
||||
import me.shedaniel.clothconfig2.api.ConfigCategory;
|
||||
import me.shedaniel.clothconfig2.api.ConfigEntryBuilder;
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiGraphics;
|
||||
import net.minecraft.client.gui.components.Button;
|
||||
import net.minecraft.client.gui.components.events.GuiEventListener;
|
||||
import net.minecraft.client.gui.narration.NarratableEntry;
|
||||
import net.minecraft.client.gui.screens.Screen;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.MutableComponent;
|
||||
import net.neoforged.neoforge.common.ForgeConfigSpec;
|
||||
|
||||
public class ModConfigScreen {
|
||||
public static Screen create(Screen parent) {
|
||||
ConfigBuilder builder = ConfigBuilder.create().setParentScreen(parent).setTitle((Component)Component.m_237115_((String)"title.explosionoverhaul.config"));
|
||||
ConfigEntryBuilder entryBuilder = builder.entryBuilder();
|
||||
ConfigCategory serverCategory = builder.getOrCreateCategory((Component)Component.m_237115_((String)"category.explosionoverhaul.server"));
|
||||
builder.setSavingRunnable(() -> {
|
||||
Config.CLIENT_SPEC.save();
|
||||
Config.COMMON_SPEC.save();
|
||||
ExplosionTextureManager.getInstance().reload();
|
||||
});
|
||||
serverCategory.addEntry((AbstractConfigListEntry)entryBuilder.startBooleanToggle((Component)Component.m_237115_((String)"option.explosionoverhaul.enableFallingBlocks"), ((Boolean)Config.COMMON.enableFallingBlocks.get()).booleanValue()).setDefaultValue(true).setTooltip(new Component[]{Component.m_237115_((String)"tooltip.explosionoverhaul.enableFallingBlocks")}).setSaveConsumer(arg_0 -> ((ForgeConfigSpec.BooleanValue)Config.COMMON.enableFallingBlocks).set(arg_0)).build());
|
||||
serverCategory.addEntry((AbstractConfigListEntry)entryBuilder.startBooleanToggle((Component)Component.m_237115_((String)"option.explosionoverhaul.enableExplosionClustering"), ((Boolean)Config.COMMON.enableExplosionClustering.get()).booleanValue()).setDefaultValue(true).setTooltip(new Component[]{Component.m_237115_((String)"tooltip.explosionoverhaul.enableExplosionClustering")}).setSaveConsumer(arg_0 -> ((ForgeConfigSpec.BooleanValue)Config.COMMON.enableExplosionClustering).set(arg_0)).build());
|
||||
serverCategory.addEntry((AbstractConfigListEntry)entryBuilder.startBooleanToggle((Component)Component.m_237115_((String)"option.explosionoverhaul.enableCraterDestruction"), ((Boolean)Config.COMMON.enableCraterDestruction.get()).booleanValue()).setDefaultValue(true).setTooltip(new Component[]{Component.m_237115_((String)"tooltip.explosionoverhaul.enableCraterDestruction")}).setSaveConsumer(arg_0 -> ((ForgeConfigSpec.BooleanValue)Config.COMMON.enableCraterDestruction).set(arg_0)).build());
|
||||
serverCategory.addEntry((AbstractConfigListEntry)entryBuilder.startBooleanToggle((Component)Component.m_237115_((String)"option.explosionoverhaul.enableGlassBreaking"), ((Boolean)Config.COMMON.enableGlassBreaking.get()).booleanValue()).setDefaultValue(true).setTooltip(new Component[]{Component.m_237115_((String)"tooltip.explosionoverhaul.enableGlassBreaking")}).setSaveConsumer(arg_0 -> ((ForgeConfigSpec.BooleanValue)Config.COMMON.enableGlassBreaking).set(arg_0)).build());
|
||||
serverCategory.addEntry((AbstractConfigListEntry)entryBuilder.startBooleanToggle((Component)Component.m_237115_((String)"option.explosionoverhaul.enableDripstoneFalling"), ((Boolean)Config.COMMON.enableDripstoneFalling.get()).booleanValue()).setDefaultValue(true).setTooltip(new Component[]{Component.m_237115_((String)"tooltip.explosionoverhaul.enableDripstoneFalling")}).setSaveConsumer(arg_0 -> ((ForgeConfigSpec.BooleanValue)Config.COMMON.enableDripstoneFalling).set(arg_0)).build());
|
||||
serverCategory.addEntry((AbstractConfigListEntry)entryBuilder.startBooleanToggle((Component)Component.m_237115_((String)"option.explosionoverhaul.enableLampFlicker"), ((Boolean)Config.COMMON.enableLampFlicker.get()).booleanValue()).setDefaultValue(true).setTooltip(new Component[]{Component.m_237115_((String)"tooltip.explosionoverhaul.enableLampFlicker")}).setSaveConsumer(arg_0 -> ((ForgeConfigSpec.BooleanValue)Config.COMMON.enableLampFlicker).set(arg_0)).build());
|
||||
serverCategory.addEntry((AbstractConfigListEntry)entryBuilder.startTextDescription((Component)Component.m_237113_((String)" ")).build());
|
||||
serverCategory.addEntry((AbstractConfigListEntry)entryBuilder.startTextDescription((Component)Component.m_237115_((String)"option.explosionoverhaul.craterSettingsHeader")).build());
|
||||
serverCategory.addEntry((AbstractConfigListEntry)entryBuilder.startIntSlider((Component)Component.m_237115_((String)"option.explosionoverhaul.craterSizeMultiplier"), (int)((Double)Config.COMMON.craterSizeMultiplier.get() * 100.0), 10, 5000).setDefaultValue(100).setTextGetter(value -> {
|
||||
double val = (double)value.intValue() / 100.0;
|
||||
Object text = String.format("%.2fx", val);
|
||||
if (val > 10.0) {
|
||||
text = (String)text + " \u00a7c(EXTREME!)";
|
||||
}
|
||||
return Component.m_237113_((String)text);
|
||||
}).setTooltipSupplier(value -> Optional.of(ModConfigScreen.generateCraterTable((double)value.intValue() / 100.0))).setSaveConsumer(newValue -> Config.COMMON.craterSizeMultiplier.set((Object)((double)newValue.intValue() / 100.0))).build());
|
||||
serverCategory.addEntry((AbstractConfigListEntry)entryBuilder.startIntSlider((Component)Component.m_237115_((String)"option.explosionoverhaul.craterCoreRatio"), (int)((Double)Config.COMMON.craterCoreRatio.get() * 100.0), 10, 95).setDefaultValue(70).setTextGetter(value -> Component.m_237113_((String)(value + "%"))).setTooltip(new Component[]{Component.m_237115_((String)"tooltip.explosionoverhaul.craterCoreRatio")}).setSaveConsumer(newValue -> Config.COMMON.craterCoreRatio.set((Object)((double)newValue.intValue() / 100.0))).build());
|
||||
serverCategory.addEntry((AbstractConfigListEntry)entryBuilder.startTextDescription((Component)Component.m_237113_((String)" ")).build());
|
||||
serverCategory.addEntry((AbstractConfigListEntry)entryBuilder.startTextDescription((Component)Component.m_237113_((String)"--- Async Crater Pipeline ---")).setTooltip(new Component[]{Component.m_237113_((String)"Computes crater geometry off-thread and applies block changes in batches per tick.")}).build());
|
||||
serverCategory.addEntry((AbstractConfigListEntry)entryBuilder.startBooleanToggle((Component)Component.m_237115_((String)"option.explosionoverhaul.enableAsyncCrater"), ((Boolean)Config.COMMON.enableAsyncCrater.get()).booleanValue()).setDefaultValue(true).setTooltip(new Component[]{Component.m_237115_((String)"tooltip.explosionoverhaul.enableAsyncCrater")}).setSaveConsumer(arg_0 -> ((ForgeConfigSpec.BooleanValue)Config.COMMON.enableAsyncCrater).set(arg_0)).build());
|
||||
serverCategory.addEntry((AbstractConfigListEntry)entryBuilder.startIntSlider((Component)Component.m_237115_((String)"option.explosionoverhaul.maxClusterPower"), ((Integer)Config.COMMON.maxClusterPower.get()).intValue(), 4, 1000).setDefaultValue(100).setTextGetter(v -> Component.m_237113_((String)String.valueOf(v))).setTooltipSupplier(v -> {
|
||||
if (v >= 500) {
|
||||
return Optional.of(new Component[]{Component.m_237115_((String)"tooltip.explosionoverhaul.maxClusterPower"), Component.m_237113_((String)""), Component.m_237113_((String)"\u26a0 ").m_130944_(new ChatFormatting[]{ChatFormatting.RED, ChatFormatting.BOLD}).m_7220_((Component)Component.m_237115_((String)"warning.explosionoverhaul.crashRisk").m_130944_(new ChatFormatting[]{ChatFormatting.DARK_RED, ChatFormatting.BOLD}))});
|
||||
}
|
||||
if (v >= 300) {
|
||||
return Optional.of(new Component[]{Component.m_237115_((String)"tooltip.explosionoverhaul.maxClusterPower"), Component.m_237113_((String)""), Component.m_237115_((String)"warning.explosionoverhaul.severeRenderingLag").m_130940_(ChatFormatting.DARK_RED)});
|
||||
}
|
||||
if (v >= 150) {
|
||||
return Optional.of(new Component[]{Component.m_237115_((String)"tooltip.explosionoverhaul.maxClusterPower"), Component.m_237113_((String)""), Component.m_237115_((String)"warning.explosionoverhaul.renderingLag").m_130940_(ChatFormatting.GOLD)});
|
||||
}
|
||||
return Optional.of(new Component[]{Component.m_237115_((String)"tooltip.explosionoverhaul.maxClusterPower")});
|
||||
}).setSaveConsumer(arg_0 -> ((ForgeConfigSpec.IntValue)Config.COMMON.maxClusterPower).set(arg_0)).build());
|
||||
int availableThreads = Runtime.getRuntime().availableProcessors();
|
||||
int maxThreadsForSystem = Math.min(32, availableThreads);
|
||||
serverCategory.addEntry((AbstractConfigListEntry)entryBuilder.startIntSlider((Component)Component.m_237115_((String)"option.explosionoverhaul.craterMaxThreads"), ((Integer)Config.COMMON.craterMaxThreads.get()).intValue(), 0, maxThreadsForSystem).setDefaultValue(0).setTextGetter(v -> Component.m_237113_((String)(v == 0 ? "Auto (" + availableThreads + ")" : String.valueOf(v)))).setTooltip(new Component[]{Component.m_237115_((String)"tooltip.explosionoverhaul.craterMaxThreads")}).setSaveConsumer(arg_0 -> ((ForgeConfigSpec.IntValue)Config.COMMON.craterMaxThreads).set(arg_0)).build());
|
||||
serverCategory.addEntry((AbstractConfigListEntry)entryBuilder.startIntSlider((Component)Component.m_237115_((String)"option.explosionoverhaul.craterApplyBlocksPerTick"), ((Integer)Config.COMMON.craterApplyBlocksPerTick.get()).intValue(), 0, 150000).setDefaultValue(50000).setTextGetter(v -> Component.m_237113_((String)(v + " blocks/tick"))).setTooltip(new Component[]{Component.m_237115_((String)"tooltip.explosionoverhaul.craterApplyBlocksPerTick")}).setSaveConsumer(arg_0 -> ((ForgeConfigSpec.IntValue)Config.COMMON.craterApplyBlocksPerTick).set(arg_0)).build());
|
||||
serverCategory.addEntry((AbstractConfigListEntry)entryBuilder.startIntSlider((Component)Component.m_237115_((String)"option.explosionoverhaul.craterMaxFallingBlocksPerTick"), ((Integer)Config.COMMON.craterMaxFallingBlocksPerTick.get()).intValue(), 0, 2000).setDefaultValue(500).setTextGetter(v -> Component.m_237113_((String)(v + " entities/tick"))).setTooltip(new Component[]{Component.m_237115_((String)"tooltip.explosionoverhaul.craterMaxFallingBlocksPerTick")}).setSaveConsumer(arg_0 -> ((ForgeConfigSpec.IntValue)Config.COMMON.craterMaxFallingBlocksPerTick).set(arg_0)).build());
|
||||
serverCategory.addEntry((AbstractConfigListEntry)entryBuilder.startBooleanToggle((Component)Component.m_237115_((String)"option.explosionoverhaul.enableDirectChunkWrites"), ((Boolean)Config.COMMON.enableDirectChunkWrites.get()).booleanValue()).setDefaultValue(true).setTooltip(new Component[]{Component.m_237115_((String)"tooltip.explosionoverhaul.enableDirectChunkWrites")}).setSaveConsumer(arg_0 -> ((ForgeConfigSpec.BooleanValue)Config.COMMON.enableDirectChunkWrites).set(arg_0)).build());
|
||||
serverCategory.addEntry((AbstractConfigListEntry)entryBuilder.startIntSlider((Component)Component.m_237115_((String)"option.explosionoverhaul.craterChunksPerTick"), ((Integer)Config.COMMON.craterChunksPerTick.get()).intValue(), 0, 500).setDefaultValue(120).setTextGetter(v -> Component.m_237113_((String)(v + " chunks/tick"))).setTooltip(new Component[]{Component.m_237115_((String)"tooltip.explosionoverhaul.craterChunksPerTick")}).setSaveConsumer(arg_0 -> ((ForgeConfigSpec.IntValue)Config.COMMON.craterChunksPerTick).set(arg_0)).build());
|
||||
serverCategory.addEntry((AbstractConfigListEntry)entryBuilder.startTextDescription((Component)Component.m_237113_((String)" ")).build());
|
||||
serverCategory.addEntry((AbstractConfigListEntry)entryBuilder.startTextDescription((Component)Component.m_237115_((String)"option.explosionoverhaul.glassBreakingSettings")).build());
|
||||
serverCategory.addEntry((AbstractConfigListEntry)entryBuilder.startIntSlider((Component)Component.m_237115_((String)"option.explosionoverhaul.glassBreakingIntervalTicks"), ((Integer)Config.COMMON.glassBreakingIntervalTicks.get()).intValue(), 1, 20).setDefaultValue(1).setTooltip(new Component[]{Component.m_237115_((String)"tooltip.explosionoverhaul.glassBreakingIntervalTicks")}).setSaveConsumer(arg_0 -> ((ForgeConfigSpec.IntValue)Config.COMMON.glassBreakingIntervalTicks).set(arg_0)).build());
|
||||
serverCategory.addEntry((AbstractConfigListEntry)entryBuilder.startIntSlider((Component)Component.m_237115_((String)"option.explosionoverhaul.glassBlocksPerCycle"), ((Integer)Config.COMMON.glassBlocksPerCycle.get()).intValue(), 10, 500).setDefaultValue(70).setTooltip(new Component[]{Component.m_237115_((String)"tooltip.explosionoverhaul.glassBlocksPerCycle")}).setSaveConsumer(arg_0 -> ((ForgeConfigSpec.IntValue)Config.COMMON.glassBlocksPerCycle).set(arg_0)).build());
|
||||
serverCategory.addEntry((AbstractConfigListEntry)entryBuilder.startTextDescription((Component)Component.m_237113_((String)" ")).build());
|
||||
serverCategory.addEntry((AbstractConfigListEntry)entryBuilder.startTextDescription((Component)Component.m_237115_((String)"option.explosionoverhaul.lampFlickerSettings")).build());
|
||||
serverCategory.addEntry((AbstractConfigListEntry)entryBuilder.startIntSlider((Component)Component.m_237115_((String)"option.explosionoverhaul.lampFlickerSearchRadius"), ((Integer)Config.COMMON.lampFlickerSearchRadius.get()).intValue(), 1, 100).setDefaultValue(50).setTooltip(new Component[]{Component.m_237115_((String)"tooltip.explosionoverhaul.lampFlickerSearchRadius")}).setSaveConsumer(arg_0 -> ((ForgeConfigSpec.IntValue)Config.COMMON.lampFlickerSearchRadius).set(arg_0)).build());
|
||||
serverCategory.addEntry((AbstractConfigListEntry)entryBuilder.startTextDescription((Component)Component.m_237115_((String)"option.explosionoverhaul.dripstoneFallingSettings")).build());
|
||||
serverCategory.addEntry((AbstractConfigListEntry)entryBuilder.startIntSlider((Component)Component.m_237115_((String)"option.explosionoverhaul.dripstoneFallingSearchRadius"), ((Integer)Config.COMMON.dripstoneFallingSearchRadius.get()).intValue(), 1, 100).setDefaultValue(50).setTooltip(new Component[]{Component.m_237115_((String)"tooltip.explosionoverhaul.dripstoneFallingSearchRadius")}).setSaveConsumer(arg_0 -> ((ForgeConfigSpec.IntValue)Config.COMMON.dripstoneFallingSearchRadius).set(arg_0)).build());
|
||||
ConfigCategory ambientCategory = builder.getOrCreateCategory((Component)Component.m_237115_((String)"category.explosionoverhaul.ambient"));
|
||||
Config.Common.Ambient ambientConfig = Config.COMMON.ambient;
|
||||
ambientCategory.addEntry((AbstractConfigListEntry)entryBuilder.startBooleanToggle((Component)Component.m_237115_((String)"option.explosionoverhaul.enableAmbientExplosions"), ((Boolean)ambientConfig.enableAmbientExplosions.get()).booleanValue()).setDefaultValue(false).setTooltip(new Component[]{Component.m_237115_((String)"tooltip.explosionoverhaul.enableAmbientExplosions")}).setSaveConsumer(arg_0 -> ((ForgeConfigSpec.BooleanValue)ambientConfig.enableAmbientExplosions).set(arg_0)).build());
|
||||
ambientCategory.addEntry((AbstractConfigListEntry)entryBuilder.startIntSlider((Component)Component.m_237115_((String)"option.explosionoverhaul.minTimeBetweenExplosions"), (Integer)ambientConfig.minTimeBetweenExplosions.get() / 20, 5, 3600).setDefaultValue(60).setTextGetter(value -> Component.m_237113_((String)(value + " s"))).setTooltip(new Component[]{Component.m_237115_((String)"tooltip.explosionoverhaul.minTimeBetweenExplosions")}).setSaveConsumer(newValue -> ambientConfig.minTimeBetweenExplosions.set((Object)(newValue * 20))).build());
|
||||
ambientCategory.addEntry((AbstractConfigListEntry)entryBuilder.startIntSlider((Component)Component.m_237115_((String)"option.explosionoverhaul.maxTimeBetweenExplosions"), (Integer)ambientConfig.maxTimeBetweenExplosions.get() / 20, 10, 3600).setDefaultValue(300).setTextGetter(value -> Component.m_237113_((String)(value + " s"))).setTooltip(new Component[]{Component.m_237115_((String)"tooltip.explosionoverhaul.maxTimeBetweenExplosions")}).setSaveConsumer(newValue -> ambientConfig.maxTimeBetweenExplosions.set((Object)(newValue * 20))).build());
|
||||
ambientCategory.addEntry((AbstractConfigListEntry)entryBuilder.startIntSlider((Component)Component.m_237115_((String)"option.explosionoverhaul.minExplosionDistance"), ((Integer)ambientConfig.minExplosionDistance.get()).intValue(), 100, 10000).setDefaultValue(501).setTextGetter(value -> Component.m_237113_((String)(value + " blocks"))).setTooltip(new Component[]{Component.m_237115_((String)"tooltip.explosionoverhaul.minExplosionDistance")}).setSaveConsumer(arg_0 -> ((ForgeConfigSpec.IntValue)ambientConfig.minExplosionDistance).set(arg_0)).build());
|
||||
ambientCategory.addEntry((AbstractConfigListEntry)entryBuilder.startIntSlider((Component)Component.m_237115_((String)"option.explosionoverhaul.maxExplosionDistance"), ((Integer)ambientConfig.maxExplosionDistance.get()).intValue(), 200, 10000).setDefaultValue(5001).setTextGetter(value -> Component.m_237113_((String)(value + " blocks"))).setTooltip(new Component[]{Component.m_237115_((String)"tooltip.explosionoverhaul.maxExplosionDistance")}).setSaveConsumer(arg_0 -> ((ForgeConfigSpec.IntValue)ambientConfig.maxExplosionDistance).set(arg_0)).build());
|
||||
ambientCategory.addEntry((AbstractConfigListEntry)entryBuilder.startIntSlider((Component)Component.m_237115_((String)"option.explosionoverhaul.maxAmbientExplosionPower"), (int)((Double)ambientConfig.maxAmbientExplosionPower.get() * 10.0), 400, 2000).setDefaultValue(800).setTextGetter(value -> Component.m_237113_((String)String.format("%.1f", (double)value.intValue() / 10.0))).setTooltip(new Component[]{Component.m_237115_((String)"tooltip.explosionoverhaul.maxAmbientExplosionPower")}).setSaveConsumer(newValue -> ambientConfig.maxAmbientExplosionPower.set((Object)((double)newValue.intValue() / 10.0))).build());
|
||||
Config.Common.Ambient.Scenarios scenariosConfig = ambientConfig.scenarios;
|
||||
ambientCategory.addEntry((AbstractConfigListEntry)entryBuilder.startTextDescription((Component)Component.m_237113_((String)" ")).build());
|
||||
ambientCategory.addEntry((AbstractConfigListEntry)entryBuilder.startTextDescription((Component)Component.m_237115_((String)"option.explosionoverhaul.scenariosHeader")).setTooltip(new Component[]{Component.m_237115_((String)"tooltip.explosionoverhaul.scenariosHeader")}).build());
|
||||
ambientCategory.addEntry((AbstractConfigListEntry)entryBuilder.startIntSlider((Component)Component.m_237115_((String)"option.explosionoverhaul.singleExplosionWeight"), ((Integer)scenariosConfig.singleExplosionWeight.get()).intValue(), 0, 100).setTextGetter(v -> Component.m_237113_((String)(v + "%"))).setDefaultValue(70).setSaveConsumer(arg_0 -> ((ForgeConfigSpec.IntValue)scenariosConfig.singleExplosionWeight).set(arg_0)).build());
|
||||
ambientCategory.addEntry((AbstractConfigListEntry)entryBuilder.startIntSlider((Component)Component.m_237115_((String)"option.explosionoverhaul.chainReactionWeight"), ((Integer)scenariosConfig.chainReactionWeight.get()).intValue(), 0, 100).setTextGetter(v -> Component.m_237113_((String)(v + "%"))).setDefaultValue(15).setSaveConsumer(arg_0 -> ((ForgeConfigSpec.IntValue)scenariosConfig.chainReactionWeight).set(arg_0)).build());
|
||||
ambientCategory.addEntry((AbstractConfigListEntry)entryBuilder.startIntSlider((Component)Component.m_237115_((String)"option.explosionoverhaul.shellingWeight"), ((Integer)scenariosConfig.shellingWeight.get()).intValue(), 0, 100).setTextGetter(v -> Component.m_237113_((String)(v + "%"))).setDefaultValue(15).setSaveConsumer(arg_0 -> ((ForgeConfigSpec.IntValue)scenariosConfig.shellingWeight).set(arg_0)).build());
|
||||
ambientCategory.addEntry((AbstractConfigListEntry)entryBuilder.startTextDescription((Component)Component.m_237115_((String)"option.explosionoverhaul.chainReactionSettingsHeader")).build());
|
||||
ambientCategory.addEntry((AbstractConfigListEntry)entryBuilder.startIntSlider((Component)Component.m_237115_((String)"option.explosionoverhaul.minChainReactionShots"), ((Integer)scenariosConfig.minChainReactionShots.get()).intValue(), 2, 20).setDefaultValue(3).setSaveConsumer(arg_0 -> ((ForgeConfigSpec.IntValue)scenariosConfig.minChainReactionShots).set(arg_0)).build());
|
||||
ambientCategory.addEntry((AbstractConfigListEntry)entryBuilder.startIntSlider((Component)Component.m_237115_((String)"option.explosionoverhaul.maxChainReactionShots"), ((Integer)scenariosConfig.maxChainReactionShots.get()).intValue(), 2, 20).setDefaultValue(7).setSaveConsumer(arg_0 -> ((ForgeConfigSpec.IntValue)scenariosConfig.maxChainReactionShots).set(arg_0)).build());
|
||||
ambientCategory.addEntry((AbstractConfigListEntry)entryBuilder.startIntSlider((Component)Component.m_237115_((String)"option.explosionoverhaul.minTimeBetweenChainShots"), ((Integer)scenariosConfig.minTimeBetweenChainShots.get()).intValue(), 5, 200).setTextGetter(v -> Component.m_237113_((String)String.format("%.2fs", (double)v.intValue() / 20.0))).setDefaultValue(10).setSaveConsumer(arg_0 -> ((ForgeConfigSpec.IntValue)scenariosConfig.minTimeBetweenChainShots).set(arg_0)).build());
|
||||
ambientCategory.addEntry((AbstractConfigListEntry)entryBuilder.startIntSlider((Component)Component.m_237115_((String)"option.explosionoverhaul.maxTimeBetweenChainShots"), ((Integer)scenariosConfig.maxTimeBetweenChainShots.get()).intValue(), 10, 400).setTextGetter(v -> Component.m_237113_((String)String.format("%.2fs", (double)v.intValue() / 20.0))).setDefaultValue(40).setSaveConsumer(arg_0 -> ((ForgeConfigSpec.IntValue)scenariosConfig.maxTimeBetweenChainShots).set(arg_0)).build());
|
||||
ambientCategory.addEntry((AbstractConfigListEntry)entryBuilder.startTextDescription((Component)Component.m_237115_((String)"option.explosionoverhaul.shellingSettingsHeader")).build());
|
||||
ambientCategory.addEntry((AbstractConfigListEntry)entryBuilder.startIntSlider((Component)Component.m_237115_((String)"option.explosionoverhaul.minShellingDelay"), ((Integer)scenariosConfig.minShellingDelay.get()).intValue(), 20, 400).setTextGetter(v -> Component.m_237113_((String)String.format("%.2fs", (double)v.intValue() / 20.0))).setDefaultValue(40).setSaveConsumer(arg_0 -> ((ForgeConfigSpec.IntValue)scenariosConfig.minShellingDelay).set(arg_0)).build());
|
||||
ambientCategory.addEntry((AbstractConfigListEntry)entryBuilder.startIntSlider((Component)Component.m_237115_((String)"option.explosionoverhaul.maxShellingDelay"), ((Integer)scenariosConfig.maxShellingDelay.get()).intValue(), 20, 400).setTextGetter(v -> Component.m_237113_((String)String.format("%.2fs", (double)v.intValue() / 20.0))).setDefaultValue(140).setSaveConsumer(arg_0 -> ((ForgeConfigSpec.IntValue)scenariosConfig.maxShellingDelay).set(arg_0)).build());
|
||||
ambientCategory.addEntry((AbstractConfigListEntry)entryBuilder.startTextDescription((Component)Component.m_237113_((String)" ")).build());
|
||||
ambientCategory.addEntry((AbstractConfigListEntry)entryBuilder.startTextDescription((Component)Component.m_237115_((String)"option.explosionoverhaul.powerTiersHeader")).setTooltip(new Component[]{Component.m_237115_((String)"tooltip.explosionoverhaul.powerTiersHeader")}).build());
|
||||
ambientCategory.addEntry((AbstractConfigListEntry)entryBuilder.startIntSlider((Component)Component.m_237115_((String)"option.explosionoverhaul.tier1_weight"), ((Integer)ambientConfig.powerTiers.tier1_weight.get()).intValue(), 0, 100).setTextGetter(v -> Component.m_237113_((String)(v + "%"))).setDefaultValue(50).setSaveConsumer(arg_0 -> ((ForgeConfigSpec.IntValue)ambientConfig.powerTiers.tier1_weight).set(arg_0)).build());
|
||||
ambientCategory.addEntry((AbstractConfigListEntry)entryBuilder.startIntSlider((Component)Component.m_237115_((String)"option.explosionoverhaul.tier2_weight"), ((Integer)ambientConfig.powerTiers.tier2_weight.get()).intValue(), 0, 100).setTextGetter(v -> Component.m_237113_((String)(v + "%"))).setDefaultValue(25).setSaveConsumer(arg_0 -> ((ForgeConfigSpec.IntValue)ambientConfig.powerTiers.tier2_weight).set(arg_0)).build());
|
||||
ambientCategory.addEntry((AbstractConfigListEntry)entryBuilder.startIntSlider((Component)Component.m_237115_((String)"option.explosionoverhaul.tier3_weight"), ((Integer)ambientConfig.powerTiers.tier3_weight.get()).intValue(), 0, 100).setTextGetter(v -> Component.m_237113_((String)(v + "%"))).setDefaultValue(15).setSaveConsumer(arg_0 -> ((ForgeConfigSpec.IntValue)ambientConfig.powerTiers.tier3_weight).set(arg_0)).build());
|
||||
ambientCategory.addEntry((AbstractConfigListEntry)entryBuilder.startIntSlider((Component)Component.m_237115_((String)"option.explosionoverhaul.tier4_weight"), ((Integer)ambientConfig.powerTiers.tier4_weight.get()).intValue(), 0, 100).setTextGetter(v -> Component.m_237113_((String)(v + "%"))).setDefaultValue(8).setSaveConsumer(arg_0 -> ((ForgeConfigSpec.IntValue)ambientConfig.powerTiers.tier4_weight).set(arg_0)).build());
|
||||
ambientCategory.addEntry((AbstractConfigListEntry)entryBuilder.startIntSlider((Component)Component.m_237115_((String)"option.explosionoverhaul.tier5_weight"), ((Integer)ambientConfig.powerTiers.tier5_weight.get()).intValue(), 0, 100).setTextGetter(v -> Component.m_237113_((String)(v + "%"))).setDefaultValue(2).setSaveConsumer(arg_0 -> ((ForgeConfigSpec.IntValue)ambientConfig.powerTiers.tier5_weight).set(arg_0)).build());
|
||||
ambientCategory.addEntry((AbstractConfigListEntry)entryBuilder.startTextDescription((Component)Component.m_237113_((String)" ")).build());
|
||||
ambientCategory.addEntry((AbstractConfigListEntry)entryBuilder.startTextDescription((Component)Component.m_237115_((String)"option.explosionoverhaul.soundTypesHeader")).build());
|
||||
ambientCategory.addEntry((AbstractConfigListEntry)entryBuilder.startBooleanToggle((Component)Component.m_237115_((String)"option.explosionoverhaul.enableSurfaceSounds"), ((Boolean)ambientConfig.soundTypes.enableSurfaceSounds.get()).booleanValue()).setTooltip(new Component[]{Component.m_237115_((String)"tooltip.explosionoverhaul.enableSurfaceSounds")}).setDefaultValue(true).setSaveConsumer(arg_0 -> ((ForgeConfigSpec.BooleanValue)ambientConfig.soundTypes.enableSurfaceSounds).set(arg_0)).build());
|
||||
ambientCategory.addEntry((AbstractConfigListEntry)entryBuilder.startBooleanToggle((Component)Component.m_237115_((String)"option.explosionoverhaul.enableCaveSounds"), ((Boolean)ambientConfig.soundTypes.enableCaveSounds.get()).booleanValue()).setTooltip(new Component[]{Component.m_237115_((String)"tooltip.explosionoverhaul.enableCaveSounds")}).setDefaultValue(true).setSaveConsumer(arg_0 -> ((ForgeConfigSpec.BooleanValue)ambientConfig.soundTypes.enableCaveSounds).set(arg_0)).build());
|
||||
ambientCategory.addEntry((AbstractConfigListEntry)entryBuilder.startBooleanToggle((Component)Component.m_237115_((String)"option.explosionoverhaul.enableAmbientCaveDust"), ((Boolean)ambientConfig.soundTypes.enableAmbientCaveDust.get()).booleanValue()).setTooltip(new Component[]{Component.m_237115_((String)"tooltip.explosionoverhaul.enableAmbientCaveDust")}).setDefaultValue(true).setSaveConsumer(arg_0 -> ((ForgeConfigSpec.BooleanValue)ambientConfig.soundTypes.enableAmbientCaveDust).set(arg_0)).build());
|
||||
ConfigCategory renderCategory = builder.getOrCreateCategory((Component)Component.m_237115_((String)"category.explosionoverhaul.render"));
|
||||
renderCategory.addEntry((AbstractConfigListEntry)entryBuilder.startEnumSelector((Component)Component.m_237115_((String)"option.explosionoverhaul.glowTextureQuality"), Config.Client.GlowTextureQuality.class, (Enum)((Config.Client.GlowTextureQuality)((Object)Config.CLIENT.glowTextureQuality.get()))).setDefaultValue((Enum)Config.Client.GlowTextureQuality.QUALITY_256).setTooltip(new Component[]{Component.m_237115_((String)"tooltip.explosionoverhaul.glowTextureQuality")}).setSaveConsumer(arg_0 -> Config.CLIENT.glowTextureQuality.set(arg_0)).setEnumNameProvider(value -> Component.m_237113_((String)(value == Config.Client.GlowTextureQuality.QUALITY_64 ? "64x" : "256x"))).build());
|
||||
renderCategory.addEntry((AbstractConfigListEntry)entryBuilder.startEnumSelector((Component)Component.m_237115_((String)"option.explosionoverhaul.particleRenderMode"), Config.Client.ParticleRenderMode.class, (Enum)((Config.Client.ParticleRenderMode)((Object)Config.CLIENT.particleRenderMode.get()))).setDefaultValue((Enum)Config.Client.ParticleRenderMode.VANILA).setTooltip(new Component[]{Component.m_237115_((String)"tooltip.explosionoverhaul.particleRenderMode")}).setSaveConsumer(arg_0 -> Config.CLIENT.particleRenderMode.set(arg_0)).setEnumNameProvider(value -> {
|
||||
if (value == Config.Client.ParticleRenderMode.VANILA) {
|
||||
return Component.m_237113_((String)"Vanilla-like");
|
||||
}
|
||||
if (value == Config.Client.ParticleRenderMode.REALISTIC_2) {
|
||||
return Component.m_237113_((String)"Realistic 2");
|
||||
}
|
||||
return Component.m_237113_((String)"Realistic");
|
||||
}).build());
|
||||
renderCategory.addEntry((AbstractConfigListEntry)entryBuilder.startIntSlider((Component)Component.m_237115_((String)"option.explosionoverhaul.particleSizeScale"), (int)((Double)Config.CLIENT.particleSizeScale.get() * 100.0), 10, 500).setDefaultValue(100).setTextGetter(value -> Component.m_237113_((String)String.format("%.2fx", (double)value.intValue() / 100.0))).setTooltip(new Component[]{Component.m_237115_((String)"tooltip.explosionoverhaul.particleSizeScale")}).setSaveConsumer(newValue -> Config.CLIENT.particleSizeScale.set((Object)((double)newValue.intValue() / 100.0))).build());
|
||||
renderCategory.addEntry((AbstractConfigListEntry)entryBuilder.startBooleanToggle((Component)Component.m_237115_((String)"option.explosionoverhaul.enableExplosionParticles"), ((Boolean)Config.CLIENT.enableExplosionParticles.get()).booleanValue()).setDefaultValue(true).setTooltip(new Component[]{Component.m_237115_((String)"tooltip.explosionoverhaul.enableExplosionParticles")}).setSaveConsumer(arg_0 -> ((ForgeConfigSpec.BooleanValue)Config.CLIENT.enableExplosionParticles).set(arg_0)).build());
|
||||
renderCategory.addEntry((AbstractConfigListEntry)entryBuilder.startTextDescription((Component)Component.m_237113_((String)" ")).build());
|
||||
renderCategory.addEntry((AbstractConfigListEntry)entryBuilder.startBooleanToggle((Component)Component.m_237115_((String)"option.explosionoverhaul.enablePlasmaParticles"), ((Boolean)Config.CLIENT.enablePlasmaParticles.get()).booleanValue()).setDefaultValue(true).setTooltip(new Component[]{Component.m_237115_((String)"tooltip.explosionoverhaul.enablePlasmaParticles")}).setSaveConsumer(arg_0 -> ((ForgeConfigSpec.BooleanValue)Config.CLIENT.enablePlasmaParticles).set(arg_0)).build());
|
||||
renderCategory.addEntry((AbstractConfigListEntry)entryBuilder.startBooleanToggle((Component)Component.m_237115_((String)"option.explosionoverhaul.enablePlasmaSmokeTrail"), ((Boolean)Config.CLIENT.enablePlasmaSmokeTrail.get()).booleanValue()).setDefaultValue(true).setTooltip(new Component[]{Component.m_237115_((String)"tooltip.explosionoverhaul.enablePlasmaSmokeTrail")}).setSaveConsumer(arg_0 -> ((ForgeConfigSpec.BooleanValue)Config.CLIENT.enablePlasmaSmokeTrail).set(arg_0)).build());
|
||||
renderCategory.addEntry((AbstractConfigListEntry)entryBuilder.startIntSlider((Component)Component.m_237115_((String)"option.explosionoverhaul.plasmaSmokeFrequency"), (int)((Double)Config.CLIENT.plasmaSmokeFrequency.get() * 100.0), 0, 100).setDefaultValue(25).setTextGetter(value -> Component.m_237113_((String)(value + "%"))).setTooltip(new Component[]{Component.m_237115_((String)"tooltip.explosionoverhaul.plasmaSmokeFrequency")}).setSaveConsumer(newValue -> Config.CLIENT.plasmaSmokeFrequency.set((Object)((double)newValue.intValue() / 100.0))).build());
|
||||
renderCategory.addEntry((AbstractConfigListEntry)entryBuilder.startIntSlider((Component)Component.m_237115_((String)"option.explosionoverhaul.plasmaSmokeCount"), ((Integer)Config.CLIENT.plasmaSmokeCount.get()).intValue(), 0, 5).setDefaultValue(1).setTextGetter(value -> Component.m_237113_((String)String.valueOf(value))).setTooltip(new Component[]{Component.m_237115_((String)"tooltip.explosionoverhaul.plasmaSmokeCount")}).setSaveConsumer(arg_0 -> ((ForgeConfigSpec.IntValue)Config.CLIENT.plasmaSmokeCount).set(arg_0)).build());
|
||||
renderCategory.addEntry((AbstractConfigListEntry)entryBuilder.startTextDescription((Component)Component.m_237113_((String)" ")).build());
|
||||
renderCategory.addEntry((AbstractConfigListEntry)entryBuilder.startBooleanToggle((Component)Component.m_237115_((String)"option.explosionoverhaul.enableFlashEffect"), ((Boolean)Config.CLIENT.enableFlashEffect.get()).booleanValue()).setDefaultValue(true).setTooltip(new Component[]{Component.m_237115_((String)"tooltip.explosionoverhaul.enableFlashEffect")}).setSaveConsumer(arg_0 -> ((ForgeConfigSpec.BooleanValue)Config.CLIENT.enableFlashEffect).set(arg_0)).build());
|
||||
renderCategory.addEntry((AbstractConfigListEntry)entryBuilder.startIntSlider((Component)Component.m_237115_((String)"option.explosionoverhaul.flashMaxOpacity"), (int)((Double)Config.CLIENT.flashMaxOpacity.get() * 100.0), 0, 100).setDefaultValue(50).setTextGetter(value -> Component.m_237113_((String)(value + "%"))).setTooltip(new Component[]{Component.m_237115_((String)"tooltip.explosionoverhaul.flashMaxOpacity")}).setSaveConsumer(newValue -> Config.CLIENT.flashMaxOpacity.set((Object)((double)newValue.intValue() / 100.0))).build());
|
||||
renderCategory.addEntry((AbstractConfigListEntry)entryBuilder.startTextDescription((Component)Component.m_237113_((String)" ")).build());
|
||||
renderCategory.addEntry((AbstractConfigListEntry)entryBuilder.startBooleanToggle((Component)Component.m_237115_((String)"option.explosionoverhaul.enableLineSparks"), ((Boolean)Config.CLIENT.enableLineSparks.get()).booleanValue()).setDefaultValue(true).setTooltip(new Component[]{Component.m_237115_((String)"tooltip.explosionoverhaul.enableLineSparks")}).setSaveConsumer(arg_0 -> ((ForgeConfigSpec.BooleanValue)Config.CLIENT.enableLineSparks).set(arg_0)).build());
|
||||
renderCategory.addEntry((AbstractConfigListEntry)entryBuilder.startIntSlider((Component)Component.m_237115_((String)"option.explosionoverhaul.lineSparkAmountMultiplier"), (int)((Double)Config.CLIENT.lineSparkAmountMultiplier.get() * 100.0), 0, 500).setDefaultValue(100).setTextGetter(value -> Component.m_237113_((String)String.format("%d%%", value))).setTooltip(new Component[]{Component.m_237115_((String)"tooltip.explosionoverhaul.lineSparkAmountMultiplier")}).setSaveConsumer(newValue -> Config.CLIENT.lineSparkAmountMultiplier.set((Object)((double)newValue.intValue() / 100.0))).build());
|
||||
renderCategory.addEntry((AbstractConfigListEntry)entryBuilder.startTextDescription((Component)Component.m_237113_((String)" ")).build());
|
||||
renderCategory.addEntry((AbstractConfigListEntry)entryBuilder.startBooleanToggle((Component)Component.m_237115_((String)"option.explosionoverhaul.enableGroundDustEffect"), ((Boolean)Config.CLIENT.enableGroundDustEffect.get()).booleanValue()).setDefaultValue(true).setTooltip(new Component[]{Component.m_237115_((String)"tooltip.explosionoverhaul.enableGroundDustEffect")}).setSaveConsumer(arg_0 -> ((ForgeConfigSpec.BooleanValue)Config.CLIENT.enableGroundDustEffect).set(arg_0)).build());
|
||||
renderCategory.addEntry((AbstractConfigListEntry)entryBuilder.startIntSlider((Component)Component.m_237115_((String)"option.explosionoverhaul.groundDustQuality"), (int)((Double)Config.CLIENT.groundDustQuality.get() * 100.0), 0, 100).setDefaultValue(100).setTextGetter(value -> Component.m_237113_((String)(value + "%"))).setTooltip(new Component[]{Component.m_237115_((String)"tooltip.explosionoverhaul.groundDustQuality")}).setSaveConsumer(newValue -> Config.CLIENT.groundDustQuality.set((Object)((double)newValue.intValue() / 100.0))).build());
|
||||
renderCategory.addEntry((AbstractConfigListEntry)entryBuilder.startIntSlider((Component)Component.m_237115_((String)"option.explosionoverhaul.groundDustRaycastFrequency"), ((Integer)Config.CLIENT.groundDustRaycastFrequency.get()).intValue(), 1, 20).setDefaultValue(10).setTooltip(new Component[]{Component.m_237115_((String)"tooltip.explosionoverhaul.groundDustRaycastFrequency")}).setSaveConsumer(arg_0 -> ((ForgeConfigSpec.IntValue)Config.CLIENT.groundDustRaycastFrequency).set(arg_0)).build());
|
||||
renderCategory.addEntry((AbstractConfigListEntry)entryBuilder.startTextDescription((Component)Component.m_237113_((String)" ")).build());
|
||||
renderCategory.addEntry((AbstractConfigListEntry)entryBuilder.startBooleanToggle((Component)Component.m_237115_((String)"option.explosionoverhaul.enableGroundMistEffect"), ((Boolean)Config.CLIENT.enableGroundMistEffect.get()).booleanValue()).setDefaultValue(true).setTooltip(new Component[]{Component.m_237115_((String)"tooltip.explosionoverhaul.enableGroundMistEffect")}).setSaveConsumer(arg_0 -> ((ForgeConfigSpec.BooleanValue)Config.CLIENT.enableGroundMistEffect).set(arg_0)).build());
|
||||
renderCategory.addEntry((AbstractConfigListEntry)entryBuilder.startIntSlider((Component)Component.m_237115_((String)"option.explosionoverhaul.groundMistQuality"), (int)((Double)Config.CLIENT.groundMistQuality.get() * 100.0), 0, 100).setDefaultValue(100).setTextGetter(value -> Component.m_237113_((String)(value + "%"))).setTooltip(new Component[]{Component.m_237115_((String)"tooltip.explosionoverhaul.groundMistQuality")}).setSaveConsumer(newValue -> Config.CLIENT.groundMistQuality.set((Object)((double)newValue.intValue() / 100.0))).build());
|
||||
renderCategory.addEntry((AbstractConfigListEntry)entryBuilder.startIntSlider((Component)Component.m_237115_((String)"option.explosionoverhaul.groundMistRaycastFrequency"), ((Integer)Config.CLIENT.groundMistRaycastFrequency.get()).intValue(), 1, 20).setDefaultValue(10).setTooltip(new Component[]{Component.m_237115_((String)"tooltip.explosionoverhaul.groundMistRaycastFrequency")}).setSaveConsumer(arg_0 -> ((ForgeConfigSpec.IntValue)Config.CLIENT.groundMistRaycastFrequency).set(arg_0)).build());
|
||||
renderCategory.addEntry((AbstractConfigListEntry)entryBuilder.startTextDescription((Component)Component.m_237113_((String)" ")).build());
|
||||
renderCategory.addEntry((AbstractConfigListEntry)entryBuilder.startBooleanToggle((Component)Component.m_237115_((String)"option.explosionoverhaul.enableShockwaveEffect"), ((Boolean)Config.CLIENT.enableShockwaveEffect.get()).booleanValue()).setDefaultValue(true).setTooltip(new Component[]{Component.m_237115_((String)"tooltip.explosionoverhaul.enableShockwaveEffect")}).setSaveConsumer(arg_0 -> ((ForgeConfigSpec.BooleanValue)Config.CLIENT.enableShockwaveEffect).set(arg_0)).build());
|
||||
renderCategory.addEntry((AbstractConfigListEntry)entryBuilder.startTextDescription((Component)Component.m_237113_((String)" ")).build());
|
||||
renderCategory.addEntry((AbstractConfigListEntry)entryBuilder.startBooleanToggle((Component)Component.m_237115_((String)"option.explosionoverhaul.enableWindEffect"), ((Boolean)Config.CLIENT.enableWindEffect.get()).booleanValue()).setDefaultValue(true).setTooltip(new Component[]{Component.m_237115_((String)"tooltip.explosionoverhaul.enableWindEffect")}).setSaveConsumer(arg_0 -> ((ForgeConfigSpec.BooleanValue)Config.CLIENT.enableWindEffect).set(arg_0)).build());
|
||||
renderCategory.addEntry((AbstractConfigListEntry)entryBuilder.startIntSlider((Component)Component.m_237115_((String)"option.explosionoverhaul.windSpeedMultiplier"), (int)((Double)Config.CLIENT.windSpeedMultiplier.get() * 100.0), 100, 200).setDefaultValue(100).setTextGetter(value -> Component.m_237113_((String)String.format("%.2fx", (double)value.intValue() / 100.0))).setTooltip(new Component[]{Component.m_237115_((String)"tooltip.explosionoverhaul.windSpeedMultiplier")}).setSaveConsumer(newValue -> Config.CLIENT.windSpeedMultiplier.set((Object)((double)newValue.intValue() / 100.0))).build());
|
||||
ConfigCategory cameraCategory = builder.getOrCreateCategory((Component)Component.m_237115_((String)"category.explosionoverhaul.camera"));
|
||||
cameraCategory.addEntry((AbstractConfigListEntry)entryBuilder.startBooleanToggle((Component)Component.m_237115_((String)"option.explosionoverhaul.enableCameraShake"), ((Boolean)Config.CLIENT.enableCameraShake.get()).booleanValue()).setDefaultValue(true).setTooltip(new Component[]{Component.m_237115_((String)"tooltip.explosionoverhaul.enableCameraShake")}).setSaveConsumer(arg_0 -> ((ForgeConfigSpec.BooleanValue)Config.CLIENT.enableCameraShake).set(arg_0)).build());
|
||||
cameraCategory.addEntry((AbstractConfigListEntry)entryBuilder.startIntSlider((Component)Component.m_237115_((String)"option.explosionoverhaul.cameraShakeAmplifier"), (int)((Double)Config.CLIENT.cameraShakeAmplifier.get() * 10.0), 0, 100).setDefaultValue(10).setTextGetter(value -> Component.m_237113_((String)String.format("%.1fx", (double)value.intValue() / 10.0))).setTooltip(new Component[]{Component.m_237115_((String)"tooltip.explosionoverhaul.cameraShakeAmplifier")}).setSaveConsumer(newValue -> Config.CLIENT.cameraShakeAmplifier.set((Object)((double)newValue.intValue() / 10.0))).build());
|
||||
cameraCategory.addEntry((AbstractConfigListEntry)entryBuilder.startTextDescription((Component)Component.m_237115_((String)"option.explosionoverhaul.cameraServerHeader")).build());
|
||||
cameraCategory.addEntry((AbstractConfigListEntry)entryBuilder.startBooleanToggle((Component)Component.m_237115_((String)"option.explosionoverhaul.enablePlayerShake"), ((Boolean)Config.COMMON.enablePlayerShake.get()).booleanValue()).setDefaultValue(true).setTooltip(new Component[]{Component.m_237115_((String)"tooltip.explosionoverhaul.enablePlayerShake")}).setSaveConsumer(arg_0 -> ((ForgeConfigSpec.BooleanValue)Config.COMMON.enablePlayerShake).set(arg_0)).build());
|
||||
cameraCategory.addEntry((AbstractConfigListEntry)entryBuilder.startIntSlider((Component)Component.m_237115_((String)"option.explosionoverhaul.playerShakeAmplifier"), (int)((Double)Config.COMMON.playerShakeAmplifier.get() * 10.0), 0, 100).setDefaultValue(10).setTextGetter(value -> Component.m_237113_((String)String.format("%.1fx", (double)value.intValue() / 10.0))).setTooltip(new Component[]{Component.m_237115_((String)"option.explosionoverhaul.playerShakeAmplifier")}).setSaveConsumer(newValue -> Config.COMMON.playerShakeAmplifier.set((Object)((double)newValue.intValue() / 10.0))).build());
|
||||
ConfigCategory scanCategory = builder.getOrCreateCategory((Component)Component.m_237115_((String)"category.explosionoverhaul.scan"));
|
||||
scanCategory.addEntry((AbstractConfigListEntry)entryBuilder.startTextDescription((Component)Component.m_237115_((String)"option.explosionoverhaul.scanSettingsHeader")).build());
|
||||
int availableCores = Runtime.getRuntime().availableProcessors();
|
||||
int maxThreads = Math.min(32, availableCores);
|
||||
scanCategory.addEntry((AbstractConfigListEntry)entryBuilder.startIntSlider((Component)Component.m_237115_((String)"option.explosionoverhaul.maxScanThreads"), ((Integer)Config.COMMON.scan.maxScanThreads.get()).intValue(), 0, maxThreads).setDefaultValue(0).setTextGetter(value -> {
|
||||
if (value == 0) {
|
||||
return Component.m_237113_((String)("Auto (" + availableCores + " threads)"));
|
||||
}
|
||||
return Component.m_237113_((String)String.valueOf(value));
|
||||
}).setTooltip(new Component[]{Component.m_237113_((String)("Maximum number of threads to use for chunk scanning.\n0 = Auto-detect (recommended): automatically uses all " + availableCores + " available threads\n1 = Single-threaded (slowest but safest for low-end servers)\n2-" + maxThreads + " = Custom thread count (available range for your system)\nYour system supports up to " + availableCores + " threads.\nMore threads = faster scanning but higher CPU usage."))}).setSaveConsumer(arg_0 -> ((ForgeConfigSpec.IntValue)Config.COMMON.scan.maxScanThreads).set(arg_0)).build());
|
||||
scanCategory.addEntry((AbstractConfigListEntry)entryBuilder.startIntSlider((Component)Component.m_237115_((String)"option.explosionoverhaul.cpuUsagePercent"), ((Integer)Config.COMMON.scan.cpuUsagePercent.get()).intValue(), 1, 100).setDefaultValue(75).setTooltip(new Component[]{Component.m_237115_((String)"tooltip.explosionoverhaul.cpuUsagePercent")}).setSaveConsumer(arg_0 -> ((ForgeConfigSpec.IntValue)Config.COMMON.scan.cpuUsagePercent).set(arg_0)).build());
|
||||
scanCategory.addEntry((AbstractConfigListEntry)entryBuilder.startBooleanToggle((Component)Component.m_237115_((String)"option.explosionoverhaul.enableBlockIndexing"), ((Boolean)Config.COMMON.scan.enableBlockIndexing.get()).booleanValue()).setDefaultValue(true).setTooltip(new Component[]{Component.m_237115_((String)"tooltip.explosionoverhaul.enableBlockIndexing")}).setSaveConsumer(arg_0 -> ((ForgeConfigSpec.BooleanValue)Config.COMMON.scan.enableBlockIndexing).set(arg_0)).build());
|
||||
scanCategory.addEntry((AbstractConfigListEntry)entryBuilder.startBooleanToggle((Component)Component.m_237115_((String)"option.explosionoverhaul.showScanProgressHUD"), ((Boolean)Config.COMMON.scan.showScanProgressHUD.get()).booleanValue()).setDefaultValue(true).setTooltip(new Component[]{Component.m_237115_((String)"tooltip.explosionoverhaul.showScanProgressHUD")}).setSaveConsumer(arg_0 -> ((ForgeConfigSpec.BooleanValue)Config.COMMON.scan.showScanProgressHUD).set(arg_0)).build());
|
||||
ConfigCategory soundsCategory = builder.getOrCreateCategory((Component)Component.m_237115_((String)"category.explosionoverhaul.sounds"));
|
||||
soundsCategory.addEntry((AbstractConfigListEntry)entryBuilder.startBooleanToggle((Component)Component.m_237115_((String)"option.explosionoverhaul.enableAdvancedSoundSpeed"), ((Boolean)Config.COMMON.enableAdvancedSoundSpeed.get()).booleanValue()).setDefaultValue(false).setTooltip(new Component[]{Component.m_237115_((String)"tooltip.explosionoverhaul.enableAdvancedSoundSpeed")}).setSaveConsumer(arg_0 -> ((ForgeConfigSpec.BooleanValue)Config.COMMON.enableAdvancedSoundSpeed).set(arg_0)).build());
|
||||
ConfigCategory concussionCategory = builder.getOrCreateCategory((Component)Component.m_237115_((String)"category.explosionoverhaul.concussion"));
|
||||
concussionCategory.addEntry((AbstractConfigListEntry)entryBuilder.startBooleanToggle((Component)Component.m_237115_((String)"option.explosionoverhaul.enableConcussion"), ((Boolean)Config.CLIENT.enableConcussion.get()).booleanValue()).setDefaultValue(true).setTooltip(new Component[]{Component.m_237115_((String)"tooltip.explosionoverhaul.enableConcussion")}).setSaveConsumer(arg_0 -> ((ForgeConfigSpec.BooleanValue)Config.CLIENT.enableConcussion).set(arg_0)).build());
|
||||
concussionCategory.addEntry((AbstractConfigListEntry)entryBuilder.startIntSlider((Component)Component.m_237115_((String)"option.explosionoverhaul.concussionDurationMultiplier"), (int)((Double)Config.CLIENT.concussionDurationMultiplier.get() * 100.0), 0, 500).setDefaultValue(100).setTextGetter(value -> Component.m_237113_((String)String.format("%.2fx", (double)value.intValue() / 100.0))).setTooltip(new Component[]{Component.m_237115_((String)"tooltip.explosionoverhaul.concussionDurationMultiplier")}).setSaveConsumer(newValue -> Config.CLIENT.concussionDurationMultiplier.set((Object)((double)newValue.intValue() / 100.0))).build());
|
||||
concussionCategory.addEntry((AbstractConfigListEntry)entryBuilder.startIntSlider((Component)Component.m_237115_((String)"option.explosionoverhaul.concussionChanceMultiplier"), (int)((Double)Config.CLIENT.concussionChanceMultiplier.get() * 100.0), 0, 500).setDefaultValue(100).setTextGetter(value -> Component.m_237113_((String)(value + "%"))).setTooltip(new Component[]{Component.m_237115_((String)"tooltip.explosionoverhaul.concussionChanceMultiplier")}).setSaveConsumer(newValue -> Config.CLIENT.concussionChanceMultiplier.set((Object)((double)newValue.intValue() / 100.0))).build());
|
||||
concussionCategory.addEntry((AbstractConfigListEntry)entryBuilder.startBooleanToggle((Component)Component.m_237115_((String)"option.explosionoverhaul.enableHeartbeatPulse"), ((Boolean)Config.CLIENT.enableHeartbeatPulse.get()).booleanValue()).setDefaultValue(true).setTooltip(new Component[]{Component.m_237115_((String)"tooltip.explosionoverhaul.enableHeartbeatPulse")}).setSaveConsumer(arg_0 -> ((ForgeConfigSpec.BooleanValue)Config.CLIENT.enableHeartbeatPulse).set(arg_0)).build());
|
||||
concussionCategory.addEntry((AbstractConfigListEntry)entryBuilder.startBooleanToggle((Component)Component.m_237115_((String)"option.explosionoverhaul.enableCameraSway"), ((Boolean)Config.CLIENT.enableCameraSway.get()).booleanValue()).setDefaultValue(true).setTooltip(new Component[]{Component.m_237115_((String)"tooltip.explosionoverhaul.enableCameraSway")}).setSaveConsumer(arg_0 -> ((ForgeConfigSpec.BooleanValue)Config.CLIENT.enableCameraSway).set(arg_0)).build());
|
||||
concussionCategory.addEntry((AbstractConfigListEntry)entryBuilder.startIntSlider((Component)Component.m_237115_((String)"option.explosionoverhaul.cameraSwayIntensity"), (int)((Double)Config.CLIENT.cameraSwayIntensity.get() * 100.0), 0, 500).setDefaultValue(100).setTextGetter(value -> Component.m_237113_((String)String.format("%.2fx", (double)value.intValue() / 100.0))).setTooltip(new Component[]{Component.m_237115_((String)"tooltip.explosionoverhaul.cameraSwayIntensity")}).setSaveConsumer(newValue -> Config.CLIENT.cameraSwayIntensity.set((Object)((double)newValue.intValue() / 100.0))).build());
|
||||
concussionCategory.addEntry((AbstractConfigListEntry)entryBuilder.startBooleanToggle((Component)Component.m_237115_((String)"option.explosionoverhaul.enableDeafness"), ((Boolean)Config.CLIENT.enableDeafness.get()).booleanValue()).setDefaultValue(true).setTooltip(new Component[]{Component.m_237115_((String)"tooltip.explosionoverhaul.enableDeafness")}).setSaveConsumer(arg_0 -> ((ForgeConfigSpec.BooleanValue)Config.CLIENT.enableDeafness).set(arg_0)).build());
|
||||
concussionCategory.addEntry((AbstractConfigListEntry)entryBuilder.startBooleanToggle((Component)Component.m_237115_((String)"option.explosionoverhaul.enableLowPass"), ((Boolean)Config.CLIENT.enableLowPass.get()).booleanValue()).setDefaultValue(true).setTooltip(new Component[]{Component.m_237115_((String)"tooltip.explosionoverhaul.enableLowPass")}).setSaveConsumer(arg_0 -> ((ForgeConfigSpec.BooleanValue)Config.CLIENT.enableLowPass).set(arg_0)).build());
|
||||
concussionCategory.addEntry((AbstractConfigListEntry)entryBuilder.startIntSlider((Component)Component.m_237115_((String)"option.explosionoverhaul.deafnessChanceMultiplier"), (int)((Double)Config.CLIENT.deafnessChanceMultiplier.get() * 100.0), 0, 500).setDefaultValue(100).setTextGetter(value -> Component.m_237113_((String)(value + "%"))).setTooltip(new Component[]{Component.m_237115_((String)"tooltip.explosionoverhaul.deafnessChanceMultiplier")}).setSaveConsumer(newValue -> Config.CLIENT.deafnessChanceMultiplier.set((Object)((double)newValue.intValue() / 100.0))).build());
|
||||
concussionCategory.addEntry((AbstractConfigListEntry)entryBuilder.startIntSlider((Component)Component.m_237115_((String)"option.explosionoverhaul.lowPassChanceMultiplier"), (int)((Double)Config.CLIENT.lowPassChanceMultiplier.get() * 100.0), 0, 500).setDefaultValue(100).setTextGetter(value -> Component.m_237113_((String)(value + "%"))).setTooltip(new Component[]{Component.m_237115_((String)"tooltip.explosionoverhaul.lowPassChanceMultiplier")}).setSaveConsumer(newValue -> Config.CLIENT.lowPassChanceMultiplier.set((Object)((double)newValue.intValue() / 100.0))).build());
|
||||
concussionCategory.addEntry((AbstractConfigListEntry)entryBuilder.startBooleanToggle((Component)Component.m_237115_((String)"option.explosionoverhaul.showHeartbeatHUD"), ((Boolean)Config.CLIENT.showHeartbeatHUD.get()).booleanValue()).setDefaultValue(false).setTooltip(new Component[]{Component.m_237115_((String)"tooltip.explosionoverhaul.showHeartbeatHUD")}).setSaveConsumer(arg_0 -> ((ForgeConfigSpec.BooleanValue)Config.CLIENT.showHeartbeatHUD).set(arg_0)).build());
|
||||
ConfigCategory blacklistCategory = builder.getOrCreateCategory((Component)Component.m_237115_((String)"category.explosionoverhaul.blacklists"));
|
||||
blacklistCategory.addEntry((AbstractConfigListEntry)new LinkButtonEntry((Component)Component.m_237115_((String)"option.explosionoverhaul.blacklist_button"), (Component)Component.m_237115_((String)"tooltip.explosionoverhaul.blacklist_button"), () -> Minecraft.m_91087_().m_91152_((Screen)new BlacklistScreen(parent))));
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
private static Component[] generateCraterTable(double multiplier) {
|
||||
int[] powerLevels;
|
||||
ArrayList<MutableComponent> lines = new ArrayList<MutableComponent>();
|
||||
lines.add(Component.m_237115_((String)"tooltip.explosionoverhaul.craterSizeMultiplier.title"));
|
||||
lines.add(Component.m_237113_((String)""));
|
||||
lines.add(Component.m_237113_((String)"\u00a7bPower \u00a78| \u00a7aApprox. Diameter"));
|
||||
lines.add(Component.m_237113_((String)"\u00a77--------------------------"));
|
||||
for (int power : powerLevels = new int[]{4, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100}) {
|
||||
float baseRadius = CraterDeformer.calculateRadius(power);
|
||||
float diameter = (float)((double)baseRadius * multiplier * 2.0);
|
||||
String formattedLine = String.format("\u00a7f%-12d\u00a78| \u00a7a~%.1f blocks", power, Float.valueOf(diameter));
|
||||
lines.add(Component.m_237113_((String)formattedLine));
|
||||
}
|
||||
lines.add(Component.m_237113_((String)"\u00a77--------------------------"));
|
||||
lines.add(Component.m_237115_((String)"tooltip.explosionoverhaul.craterSizeMultiplier.footer"));
|
||||
lines.add(Component.m_237113_((String)""));
|
||||
lines.add(Component.m_237115_((String)"tooltip.explosionoverhaul.craterShapeInfo"));
|
||||
return lines.toArray(new Component[0]);
|
||||
}
|
||||
|
||||
public static class LinkButtonEntry
|
||||
extends AbstractConfigListEntry<Object> {
|
||||
private final Button button;
|
||||
private final Component tooltip;
|
||||
|
||||
public LinkButtonEntry(Component fieldName, Component tooltip, Runnable action) {
|
||||
super(fieldName, false);
|
||||
this.tooltip = tooltip;
|
||||
this.button = Button.m_253074_((Component)fieldName, b -> action.run()).m_253136_();
|
||||
this.button.m_93674_(200);
|
||||
}
|
||||
|
||||
public void render(GuiGraphics graphics, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean isSelected, float delta) {
|
||||
this.button.m_252865_(x + entryWidth / 2 - 100);
|
||||
this.button.m_253211_(y);
|
||||
this.button.m_88315_(graphics, mouseX, mouseY, delta);
|
||||
if (mouseX >= this.button.m_252754_() && mouseX <= this.button.m_252754_() + this.button.m_5711_() && mouseY >= this.button.m_252907_() && mouseY <= this.button.m_252907_() + this.button.m_93694_()) {
|
||||
graphics.m_280557_(Minecraft.m_91087_().f_91062_, this.tooltip, mouseX, mouseY);
|
||||
}
|
||||
}
|
||||
|
||||
public List<? extends GuiEventListener> m_6702_() {
|
||||
return Collections.singletonList(this.button);
|
||||
}
|
||||
|
||||
public List<? extends NarratableEntry> narratables() {
|
||||
return Collections.singletonList(this.button);
|
||||
}
|
||||
|
||||
public Object getValue() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Optional<Object> getDefaultValue() {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
public void save() {
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul.client;
|
||||
|
||||
import com.mojang.blaze3d.platform.InputConstants;
|
||||
import net.minecraft.client.KeyMapping;
|
||||
import net.neoforged.neoforge.client.event.RegisterKeyMappingsEvent;
|
||||
|
||||
public class ModKeyMappings {
|
||||
public static final String KEY_CATEGORY = "key.categories.explosionoverhaul";
|
||||
public static final KeyMapping ACCEPT_SCAN = new KeyMapping("key.explosionoverhaul.accept_scan", InputConstants.Type.KEYSYM, 49, "key.categories.explosionoverhaul");
|
||||
public static final KeyMapping DECLINE_SCAN = new KeyMapping("key.explosionoverhaul.decline_scan", InputConstants.Type.KEYSYM, 50, "key.categories.explosionoverhaul");
|
||||
public static final KeyMapping INFO_SCAN = new KeyMapping("key.explosionoverhaul.info_scan", InputConstants.Type.KEYSYM, 51, "key.categories.explosionoverhaul");
|
||||
|
||||
public static void register(RegisterKeyMappingsEvent event) {
|
||||
event.register(ACCEPT_SCAN);
|
||||
event.register(DECLINE_SCAN);
|
||||
event.register(INFO_SCAN);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,210 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul.client;
|
||||
|
||||
import com.vinlanx.explosionoverhaul.Config;
|
||||
import com.vinlanx.explosionoverhaul.CustomGlowParticleOptions;
|
||||
import com.vinlanx.explosionoverhaul.PlasmaParticleOptions;
|
||||
import com.vinlanx.explosionoverhaul.client.ExplosionWindController;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Random;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.core.particles.ParticleOptions;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
public class PhysicsBasedExplosionEffect {
|
||||
private final ClientLevel level;
|
||||
private final Random random;
|
||||
private final Vec3 position;
|
||||
private final float power;
|
||||
private int age = 0;
|
||||
private final int maxAge = 8;
|
||||
private final float maxRadius;
|
||||
private final int particleCount;
|
||||
private final float particleScaleBase;
|
||||
private final int totalLifetime;
|
||||
private boolean finished = false;
|
||||
private final int totalSparks;
|
||||
private float sparkSpawnAccumulator = 0.0f;
|
||||
private final List<Vec3> sparkDirections;
|
||||
private int sparkIndex = 0;
|
||||
|
||||
public PhysicsBasedExplosionEffect(Vec3 position, float power) {
|
||||
this.position = position;
|
||||
this.power = power;
|
||||
this.random = new Random();
|
||||
this.level = Minecraft.m_91087_().f_91073_;
|
||||
if (this.level == null) {
|
||||
this.finished = true;
|
||||
this.maxRadius = 0.0f;
|
||||
this.particleCount = 0;
|
||||
this.particleScaleBase = 0.0f;
|
||||
this.totalLifetime = 0;
|
||||
this.totalSparks = 0;
|
||||
this.sparkDirections = new ArrayList<Vec3>();
|
||||
return;
|
||||
}
|
||||
float calcPower = Mth.m_14036_((float)power, (float)1.0f, (float)100.0f);
|
||||
float powerFraction = calcPower / 100.0f;
|
||||
this.maxRadius = Mth.m_14179_((float)powerFraction, (float)3.0f, (float)40.0f);
|
||||
this.particleCount = (int)Mth.m_14179_((float)powerFraction, (float)40.0f, (float)400.0f);
|
||||
this.particleScaleBase = Mth.m_14179_((float)powerFraction, (float)5.0f, (float)37.5f);
|
||||
this.totalLifetime = (int)Mth.m_14179_((float)powerFraction, (float)300.0f, (float)1800.0f) + this.random.nextInt(100) - 50;
|
||||
this.totalSparks = (int)Mth.m_14179_((float)powerFraction, (float)3.0f, (float)150.0f);
|
||||
this.sparkDirections = new ArrayList<Vec3>();
|
||||
if (this.totalSparks > 0) {
|
||||
double goldenRatio = (1.0 + Math.sqrt(5.0)) / 2.0;
|
||||
double angleIncrement = Math.PI * 2 * goldenRatio;
|
||||
for (int i = 0; i < this.totalSparks; ++i) {
|
||||
double y = 1.0 - (double)i / (double)(this.totalSparks - 1) * 2.0;
|
||||
double radius = Math.sqrt(1.0 - y * y);
|
||||
double theta = angleIncrement * (double)i;
|
||||
double x = Math.cos(theta) * radius;
|
||||
double z = Math.sin(theta) * radius;
|
||||
this.sparkDirections.add(new Vec3(x, z, y).m_82541_());
|
||||
}
|
||||
Collections.shuffle(this.sparkDirections, this.random);
|
||||
}
|
||||
}
|
||||
|
||||
public void tick() {
|
||||
if (this.finished) {
|
||||
return;
|
||||
}
|
||||
if (!((Boolean)Config.CLIENT.enableExplosionParticles.get()).booleanValue()) {
|
||||
this.finished = true;
|
||||
return;
|
||||
}
|
||||
++this.age;
|
||||
if (this.age > this.maxAge) {
|
||||
this.finished = true;
|
||||
return;
|
||||
}
|
||||
if (Config.CLIENT.particleRenderMode.get() == Config.Client.ParticleRenderMode.REALISTIC_2) {
|
||||
this.tickRealistic2();
|
||||
} else {
|
||||
this.tickRegular();
|
||||
}
|
||||
}
|
||||
|
||||
private void tickRealistic2() {
|
||||
if (this.age == 1) {
|
||||
double distance;
|
||||
float f = this.age;
|
||||
Objects.requireNonNull(this);
|
||||
float progress = f / 8.0f;
|
||||
float currentRadius = this.maxRadius * (float)Math.pow(progress, 0.4);
|
||||
Vec3 particlePos = this.position.m_82520_((this.random.nextDouble() - 0.5) * (double)currentRadius, (this.random.nextDouble() - 0.5) * (double)currentRadius, (this.random.nextDouble() - 0.5) * (double)currentRadius);
|
||||
Vec3 motion = new Vec3((this.random.nextDouble() - 0.5) * 0.05, (this.random.nextDouble() - 0.5) * 0.05, (this.random.nextDouble() - 0.5) * 0.05);
|
||||
double distance3D = particlePos.m_82554_(this.position);
|
||||
double heightPercent = this.maxRadius <= 0.0f ? 0.5 : Mth.m_14008_((double)(distance3D / (double)this.maxRadius), (double)0.25, (double)1.0);
|
||||
Vec3 windDirection = ExplosionWindController.getWindDirection();
|
||||
double glowSpeed = ExplosionWindController.computeGlowSpeed(heightPercent);
|
||||
if (windDirection != Vec3.f_82478_ && glowSpeed > 0.0) {
|
||||
motion = motion.m_82549_(windDirection.m_82490_(glowSpeed * 0.6));
|
||||
}
|
||||
int zone = (distance = particlePos.m_82554_(this.position)) / (double)this.maxRadius < 0.4 ? 1 : 0;
|
||||
float particleScale = this.particleScaleBase * 1.0f * ((Double)Config.CLIENT.particleSizeScale.get()).floatValue();
|
||||
int animationType = this.power <= 5.0f ? 2 : this.random.nextInt(2);
|
||||
CustomGlowParticleOptions options = new CustomGlowParticleOptions(zone, this.power, particleScale, animationType, (float)this.position.f_82480_, this.maxRadius, (float)heightPercent);
|
||||
this.level.m_7106_((ParticleOptions)options, particlePos.f_82479_, particlePos.f_82480_, particlePos.f_82481_, motion.f_82479_, motion.f_82480_, motion.f_82481_);
|
||||
}
|
||||
if (this.totalSparks > 0 && this.sparkIndex < this.totalSparks && ((Boolean)Config.CLIENT.enablePlasmaParticles.get()).booleanValue()) {
|
||||
float f = this.age;
|
||||
Objects.requireNonNull(this);
|
||||
float progress2 = f / 8.0f;
|
||||
float currentRadius2 = this.maxRadius * (float)Math.pow(progress2, 0.4);
|
||||
float f2 = this.totalSparks;
|
||||
Objects.requireNonNull(this);
|
||||
float sparksToSpawnThisTick = f2 / 8.0f;
|
||||
this.sparkSpawnAccumulator += sparksToSpawnThisTick;
|
||||
int sparksToActuallySpawn = (int)this.sparkSpawnAccumulator;
|
||||
if (sparksToActuallySpawn > 0) {
|
||||
this.sparkSpawnAccumulator -= (float)sparksToActuallySpawn;
|
||||
for (int j = 0; j < sparksToActuallySpawn && this.sparkIndex < this.totalSparks; ++j) {
|
||||
Vec3 plasmaMotion = this.sparkDirections.get(this.sparkIndex);
|
||||
++this.sparkIndex;
|
||||
Vec3 plasmaSpawnPos = this.position.m_82549_(plasmaMotion.m_82490_((double)currentRadius2 * 0.8));
|
||||
float strongSparkChance = 0.1f;
|
||||
if (this.power > 10.0f) {
|
||||
float powerFractionForChance = Mth.m_184655_((float)this.power, (float)10.0f, (float)100.0f);
|
||||
strongSparkChance = Mth.m_14179_((float)powerFractionForChance, (float)0.1f, (float)0.35f);
|
||||
}
|
||||
float force = this.random.nextFloat() < strongSparkChance ? Mth.m_14179_((float)(this.power / 100.0f), (float)2.0f, (float)14.0f) * (0.9f + this.random.nextFloat() * 0.4f) : Mth.m_14179_((float)(this.power / 100.0f), (float)1.3f, (float)6.5f) * (0.6f + this.random.nextFloat() * 0.4f);
|
||||
plasmaMotion = plasmaMotion.m_82490_((double)force);
|
||||
PlasmaParticleOptions plasmaOptions = new PlasmaParticleOptions(this.power);
|
||||
this.level.m_6493_((ParticleOptions)plasmaOptions, true, plasmaSpawnPos.f_82479_, plasmaSpawnPos.f_82480_, plasmaSpawnPos.f_82481_, plasmaMotion.f_82479_, plasmaMotion.f_82480_, plasmaMotion.f_82481_);
|
||||
}
|
||||
}
|
||||
}
|
||||
this.finished = false;
|
||||
}
|
||||
|
||||
private void tickRegular() {
|
||||
int particlesThisTick = this.particleCount / this.maxAge;
|
||||
if (this.age == this.maxAge) {
|
||||
particlesThisTick = this.particleCount - particlesThisTick * (this.maxAge - 1);
|
||||
}
|
||||
float f = this.age;
|
||||
Objects.requireNonNull(this);
|
||||
float progress = f / 8.0f;
|
||||
float currentRadius = this.maxRadius * (float)Math.pow(progress, 0.4);
|
||||
for (int i = 0; i < particlesThisTick; ++i) {
|
||||
double distance;
|
||||
double u = this.random.nextDouble();
|
||||
double v = this.random.nextDouble();
|
||||
double theta = Math.PI * 2 * u;
|
||||
double phi = Math.acos(2.0 * v - 1.0);
|
||||
double r = currentRadius;
|
||||
Vec3 particlePos = this.position.m_82520_(r * Math.sin(phi) * Math.cos(theta), r * Math.sin(phi) * Math.sin(theta), r * Math.cos(phi));
|
||||
Vec3 motion = new Vec3((this.random.nextDouble() - 0.5) * 0.05, (this.random.nextDouble() - 0.5) * 0.05, (this.random.nextDouble() - 0.5) * 0.05);
|
||||
double distance3D = particlePos.m_82554_(this.position);
|
||||
double heightPercent = this.maxRadius <= 0.0f ? 0.5 : Mth.m_14008_((double)(distance3D / (double)this.maxRadius), (double)0.25, (double)1.0);
|
||||
Vec3 windDirection = ExplosionWindController.getWindDirection();
|
||||
double glowSpeed = ExplosionWindController.computeGlowSpeed(heightPercent);
|
||||
if (windDirection != Vec3.f_82478_ && glowSpeed > 0.0) {
|
||||
motion = motion.m_82549_(windDirection.m_82490_(glowSpeed * 0.6));
|
||||
}
|
||||
int zone = (distance = particlePos.m_82554_(this.position)) / (double)this.maxRadius < 0.4 ? 1 : 0;
|
||||
float particleScale = this.particleScaleBase * (0.8f + this.random.nextFloat() * 0.4f) * ((Double)Config.CLIENT.particleSizeScale.get()).floatValue();
|
||||
int animationType = this.power <= 5.0f ? 2 : this.random.nextInt(2);
|
||||
CustomGlowParticleOptions options = new CustomGlowParticleOptions(zone, this.power, particleScale, animationType, (float)this.position.f_82480_, this.maxRadius, (float)heightPercent);
|
||||
this.level.m_7106_((ParticleOptions)options, particlePos.f_82479_, particlePos.f_82480_, particlePos.f_82481_, motion.f_82479_, motion.f_82480_, motion.f_82481_);
|
||||
}
|
||||
if (this.totalSparks > 0 && this.sparkIndex < this.totalSparks && ((Boolean)Config.CLIENT.enablePlasmaParticles.get()).booleanValue()) {
|
||||
float f2 = this.totalSparks;
|
||||
Objects.requireNonNull(this);
|
||||
float sparksToSpawnThisTick = f2 / 8.0f;
|
||||
this.sparkSpawnAccumulator += sparksToSpawnThisTick;
|
||||
int sparksToActuallySpawn = (int)this.sparkSpawnAccumulator;
|
||||
if (sparksToActuallySpawn > 0) {
|
||||
this.sparkSpawnAccumulator -= (float)sparksToActuallySpawn;
|
||||
for (int j = 0; j < sparksToActuallySpawn && this.sparkIndex < this.totalSparks; ++j) {
|
||||
Vec3 plasmaMotion = this.sparkDirections.get(this.sparkIndex);
|
||||
++this.sparkIndex;
|
||||
Vec3 plasmaSpawnPos = this.position.m_82549_(plasmaMotion.m_82490_((double)currentRadius * 0.8));
|
||||
float strongSparkChance = 0.1f;
|
||||
if (this.power > 10.0f) {
|
||||
float powerFractionForChance = Mth.m_184655_((float)this.power, (float)10.0f, (float)100.0f);
|
||||
strongSparkChance = Mth.m_14179_((float)powerFractionForChance, (float)0.1f, (float)0.35f);
|
||||
}
|
||||
float force = this.random.nextFloat() < strongSparkChance ? Mth.m_14179_((float)(this.power / 100.0f), (float)2.0f, (float)14.0f) * (0.9f + this.random.nextFloat() * 0.4f) : Mth.m_14179_((float)(this.power / 100.0f), (float)1.3f, (float)6.5f) * (0.6f + this.random.nextFloat() * 0.4f);
|
||||
plasmaMotion = plasmaMotion.m_82490_((double)force);
|
||||
PlasmaParticleOptions plasmaOptions = new PlasmaParticleOptions(this.power);
|
||||
this.level.m_6493_((ParticleOptions)plasmaOptions, true, plasmaSpawnPos.f_82479_, plasmaSpawnPos.f_82480_, plasmaSpawnPos.f_82481_, plasmaMotion.f_82479_, plasmaMotion.f_82480_, plasmaMotion.f_82481_);
|
||||
}
|
||||
}
|
||||
}
|
||||
this.finished = false;
|
||||
}
|
||||
|
||||
public boolean isFinished() {
|
||||
return this.finished;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul.client;
|
||||
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||
import com.vinlanx.explosionoverhaul.Config;
|
||||
import com.vinlanx.explosionoverhaul.PlasmaParticleOptions;
|
||||
import com.vinlanx.explosionoverhaul.SmokeParticleOptions;
|
||||
import net.minecraft.client.Camera;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.client.particle.Particle;
|
||||
import net.minecraft.client.particle.ParticleProvider;
|
||||
import net.minecraft.client.particle.ParticleRenderType;
|
||||
import net.minecraft.client.particle.SpriteSet;
|
||||
import net.minecraft.client.particle.TextureSheetParticle;
|
||||
import net.minecraft.core.particles.ParticleOptions;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.joml.Quaternionf;
|
||||
import org.joml.Quaternionfc;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
public class PlasmaParticle
|
||||
extends TextureSheetParticle {
|
||||
private final SpriteSet sprites;
|
||||
private final float initialQuadSize;
|
||||
|
||||
protected PlasmaParticle(ClientLevel pLevel, double pX, double pY, double pZ, double pXSpeed, double pYSpeed, double pZSpeed, PlasmaParticleOptions options, SpriteSet pSpriteSet) {
|
||||
super(pLevel, pX, pY, pZ, pXSpeed, pYSpeed, pZSpeed);
|
||||
this.sprites = pSpriteSet;
|
||||
this.f_172258_ = 0.96f;
|
||||
this.f_107226_ = 0.2f;
|
||||
this.f_107215_ = pXSpeed;
|
||||
this.f_107216_ = pYSpeed;
|
||||
this.f_107217_ = pZSpeed;
|
||||
float power = options.getPower();
|
||||
float powerFraction = Mth.m_14036_((float)(power / 100.0f), (float)0.0f, (float)1.0f);
|
||||
this.f_107663_ = this.initialQuadSize = Mth.m_14179_((float)powerFraction, (float)0.4f, (float)2.5f);
|
||||
this.f_107225_ = 200 + this.f_107223_.m_188503_(40) - 20;
|
||||
this.f_107227_ = 0.8f;
|
||||
this.f_107228_ = 0.8f;
|
||||
this.f_107229_ = 0.8f;
|
||||
this.m_108335_(pSpriteSet);
|
||||
}
|
||||
|
||||
public ParticleRenderType m_7556_() {
|
||||
return ParticleRenderType.f_107431_;
|
||||
}
|
||||
|
||||
public int m_6355_(float pPartialTick) {
|
||||
return 240;
|
||||
}
|
||||
|
||||
public void m_5744_(VertexConsumer pBuffer, Camera pRenderInfo, float pPartialTicks) {
|
||||
RenderSystem.disableDepthTest();
|
||||
Vec3 vec3 = pRenderInfo.m_90583_();
|
||||
float f = (float)(Mth.m_14139_((double)pPartialTicks, (double)this.f_107209_, (double)this.f_107212_) - vec3.m_7096_());
|
||||
float f1 = (float)(Mth.m_14139_((double)pPartialTicks, (double)this.f_107210_, (double)this.f_107213_) - vec3.m_7098_());
|
||||
float f2 = (float)(Mth.m_14139_((double)pPartialTicks, (double)this.f_107211_, (double)this.f_107214_) - vec3.m_7094_());
|
||||
Quaternionf quaternion = new Quaternionf((Quaternionfc)pRenderInfo.m_253121_());
|
||||
if (this.f_107231_ != 0.0f) {
|
||||
float f3 = Mth.m_14179_((float)pPartialTicks, (float)this.f_107204_, (float)this.f_107231_);
|
||||
quaternion.rotateZ(f3);
|
||||
}
|
||||
Vector3f[] avector3f = new Vector3f[]{new Vector3f(-1.0f, -1.0f, 0.0f), new Vector3f(-1.0f, 1.0f, 0.0f), new Vector3f(1.0f, 1.0f, 0.0f), new Vector3f(1.0f, -1.0f, 0.0f)};
|
||||
float f4 = this.m_5902_(pPartialTicks);
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
Vector3f vector3f = avector3f[i];
|
||||
vector3f.rotate((Quaternionfc)quaternion);
|
||||
vector3f.mul(f4);
|
||||
vector3f.add(f, f1, f2);
|
||||
}
|
||||
float f7 = this.m_5970_();
|
||||
float f8 = this.m_5952_();
|
||||
float f5 = this.m_5951_();
|
||||
float f6 = this.m_5950_();
|
||||
int j = this.m_6355_(pPartialTicks);
|
||||
pBuffer.m_5483_((double)avector3f[0].x(), (double)avector3f[0].y(), (double)avector3f[0].z()).m_7421_(f8, f6).m_85950_(this.f_107227_, this.f_107228_, this.f_107229_, this.f_107230_).m_85969_(j).m_5752_();
|
||||
pBuffer.m_5483_((double)avector3f[1].x(), (double)avector3f[1].y(), (double)avector3f[1].z()).m_7421_(f8, f5).m_85950_(this.f_107227_, this.f_107228_, this.f_107229_, this.f_107230_).m_85969_(j).m_5752_();
|
||||
pBuffer.m_5483_((double)avector3f[2].x(), (double)avector3f[2].y(), (double)avector3f[2].z()).m_7421_(f7, f5).m_85950_(this.f_107227_, this.f_107228_, this.f_107229_, this.f_107230_).m_85969_(j).m_5752_();
|
||||
pBuffer.m_5483_((double)avector3f[3].x(), (double)avector3f[3].y(), (double)avector3f[3].z()).m_7421_(f7, f6).m_85950_(this.f_107227_, this.f_107228_, this.f_107229_, this.f_107230_).m_85969_(j).m_5752_();
|
||||
RenderSystem.enableDepthTest();
|
||||
}
|
||||
|
||||
public void m_5989_() {
|
||||
super.m_5989_();
|
||||
this.m_108339_(this.sprites);
|
||||
if (!this.f_107220_) {
|
||||
float lifeProgress = (float)this.f_107224_ / (float)this.f_107225_;
|
||||
float flicker = 1.0f - this.f_107223_.m_188501_() * 0.3f;
|
||||
this.f_107230_ = Mth.m_14036_((float)(flicker * (1.0f - lifeProgress * lifeProgress)), (float)0.0f, (float)1.0f);
|
||||
this.f_107663_ = this.initialQuadSize * (0.9f + this.f_107223_.m_188501_() * 0.2f);
|
||||
if (((Boolean)Config.CLIENT.enablePlasmaSmokeTrail.get()).booleanValue() && this.f_107224_ > 2 && (double)this.f_107223_.m_188501_() < (Double)Config.CLIENT.plasmaSmokeFrequency.get()) {
|
||||
int smokeCount = (Integer)Config.CLIENT.plasmaSmokeCount.get();
|
||||
for (int i = 0; i < smokeCount; ++i) {
|
||||
this.f_107208_.m_7106_((ParticleOptions)new SmokeParticleOptions(0.5f, 200, 0.6f, 0.6f, 0.6f, 0.4f, false, 0.0f, 0.0f, null), this.f_107212_, this.f_107213_, this.f_107214_, (this.f_107223_.m_188500_() - 0.5) * 0.03, (this.f_107223_.m_188500_() - 0.5) * 0.03, (this.f_107223_.m_188500_() - 0.5) * 0.03);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class Provider
|
||||
implements ParticleProvider<PlasmaParticleOptions> {
|
||||
private final SpriteSet sprites;
|
||||
|
||||
public Provider(SpriteSet pSprites) {
|
||||
this.sprites = pSprites;
|
||||
}
|
||||
|
||||
public Particle createParticle(PlasmaParticleOptions pType, ClientLevel pLevel, double pX, double pY, double pZ, double pXSpeed, double pYSpeed, double pZSpeed) {
|
||||
return new PlasmaParticle(pLevel, pX, pY, pZ, pXSpeed, pYSpeed, pZSpeed, pType, this.sprites);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul.client;
|
||||
|
||||
import net.minecraft.client.resources.sounds.AbstractTickableSoundInstance;
|
||||
import net.minecraft.client.resources.sounds.SoundInstance;
|
||||
import net.minecraft.sounds.SoundEvent;
|
||||
import net.minecraft.sounds.SoundSource;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
public class PositionalSoundInstance
|
||||
extends AbstractTickableSoundInstance {
|
||||
public PositionalSoundInstance(SoundEvent pSound, SoundSource pSource, float pVolume, float pPitch, RandomSource pRandom, double pX, double pY, double pZ) {
|
||||
super(pSound, pSource, pRandom);
|
||||
this.f_119573_ = pVolume;
|
||||
this.f_119574_ = pPitch;
|
||||
this.f_119575_ = pX;
|
||||
this.f_119576_ = pY;
|
||||
this.f_119577_ = pZ;
|
||||
this.f_119578_ = false;
|
||||
this.f_119579_ = 0;
|
||||
this.f_119582_ = false;
|
||||
this.f_119580_ = SoundInstance.Attenuation.LINEAR;
|
||||
}
|
||||
|
||||
public void m_7788_() {
|
||||
}
|
||||
|
||||
public void updatePosition(Vec3 newPosition) {
|
||||
this.f_119575_ = newPosition.m_7096_();
|
||||
this.f_119576_ = newPosition.m_7098_();
|
||||
this.f_119577_ = newPosition.m_7094_();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul.client;
|
||||
|
||||
import com.vinlanx.explosionoverhaul.Config;
|
||||
import java.util.Random;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.core.particles.ParticleOptions;
|
||||
import net.minecraft.core.particles.ParticleTypes;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
public class ShockwaveEffect {
|
||||
private final ClientLevel level;
|
||||
private final Vec3 position;
|
||||
private final float power;
|
||||
private final Random random = new Random();
|
||||
private int age = 0;
|
||||
private final int maxAge;
|
||||
private final float maxRadius;
|
||||
private final int particlesPerTick;
|
||||
private final float shellThickness;
|
||||
private boolean finished = false;
|
||||
|
||||
public ShockwaveEffect(Vec3 position, float power) {
|
||||
this.level = Minecraft.m_91087_().f_91073_;
|
||||
this.position = position;
|
||||
this.power = power;
|
||||
float powerFraction = Mth.m_184655_((float)this.power, (float)5.0f, (float)100.0f);
|
||||
this.maxAge = (int)Mth.m_14179_((float)powerFraction, (float)4.0f, (float)7.0f);
|
||||
float fireballPowerFraction = Mth.m_14036_((float)power, (float)1.0f, (float)100.0f) / 100.0f;
|
||||
float fireballRadius = Mth.m_14179_((float)fireballPowerFraction, (float)3.0f, (float)40.0f);
|
||||
float normalizedPowerSqrt = Mth.m_184655_((float)((float)Math.sqrt(power)), (float)((float)Math.sqrt(5.0)), (float)((float)Math.sqrt(100.0)));
|
||||
float shockwaveMultiplier = Mth.m_14179_((float)normalizedPowerSqrt, (float)2.0f, (float)8.0f);
|
||||
this.maxRadius = fireballRadius * shockwaveMultiplier * 3.0f;
|
||||
this.particlesPerTick = (int)Mth.m_14179_((float)powerFraction, (float)70.0f, (float)400.0f);
|
||||
this.shellThickness = Mth.m_14179_((float)powerFraction, (float)0.5f, (float)4.0f);
|
||||
}
|
||||
|
||||
public void tick() {
|
||||
if (this.finished || this.level == null) {
|
||||
return;
|
||||
}
|
||||
if (!((Boolean)Config.CLIENT.enableShockwaveEffect.get()).booleanValue()) {
|
||||
this.finished = true;
|
||||
return;
|
||||
}
|
||||
++this.age;
|
||||
if (this.age > this.maxAge) {
|
||||
this.finished = true;
|
||||
return;
|
||||
}
|
||||
float progress = (float)this.age / (float)this.maxAge;
|
||||
float easedProgress = Mth.m_14031_((float)(progress * (float)Math.PI / 2.0f));
|
||||
float currentRadius = this.maxRadius * easedProgress;
|
||||
for (int i = 0; i < this.particlesPerTick; ++i) {
|
||||
double u = this.random.nextDouble();
|
||||
double v = this.random.nextDouble();
|
||||
double theta = Math.PI * 2 * u;
|
||||
double phi = Math.acos(2.0 * v - 1.0);
|
||||
float radiusOffset = (this.random.nextFloat() - 0.5f) * this.shellThickness;
|
||||
float finalRadius = currentRadius + radiusOffset;
|
||||
if (finalRadius < 0.0f) {
|
||||
finalRadius = 0.0f;
|
||||
}
|
||||
Vec3 particlePos = this.position.m_82520_((double)finalRadius * Math.sin(phi) * Math.cos(theta), (double)finalRadius * Math.sin(phi) * Math.sin(theta), (double)finalRadius * Math.cos(phi));
|
||||
this.level.m_6493_((ParticleOptions)ParticleTypes.f_123813_, true, particlePos.f_82479_, particlePos.f_82480_, particlePos.f_82481_, 0.0, 0.0, 0.0);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isFinished() {
|
||||
return this.finished;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul.client;
|
||||
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||
import com.vinlanx.explosionoverhaul.SmokeParticleOptions;
|
||||
import com.vinlanx.explosionoverhaul.client.ExplosionWindController;
|
||||
import net.minecraft.client.Camera;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.client.particle.Particle;
|
||||
import net.minecraft.client.particle.ParticleProvider;
|
||||
import net.minecraft.client.particle.ParticleRenderType;
|
||||
import net.minecraft.client.particle.SpriteSet;
|
||||
import net.minecraft.client.particle.TextureSheetParticle;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
public class SmokeParticle
|
||||
extends TextureSheetParticle {
|
||||
private final float initialAlpha;
|
||||
private final boolean isHeavy;
|
||||
private final float windSpeed;
|
||||
private final float heightPercent;
|
||||
|
||||
protected SmokeParticle(ClientLevel pLevel, double pX, double pY, double pZ, double pXSpeed, double pYSpeed, double pZSpeed, SmokeParticleOptions options, SpriteSet spriteSet) {
|
||||
super(pLevel, pX, pY, pZ, pXSpeed, pYSpeed, pZSpeed);
|
||||
this.f_172258_ = 0.96f;
|
||||
this.f_107226_ = 0.0f;
|
||||
this.f_107225_ = options.getLifetime();
|
||||
this.f_107663_ = options.getScale();
|
||||
this.f_107227_ = options.getRed();
|
||||
this.f_107228_ = options.getGreen();
|
||||
this.f_107229_ = options.getBlue();
|
||||
this.f_107230_ = options.getAlpha();
|
||||
this.initialAlpha = options.getAlpha();
|
||||
this.isHeavy = options.isHeavy();
|
||||
this.windSpeed = options.getWindSpeed();
|
||||
this.heightPercent = options.getHeightPercent();
|
||||
this.m_108337_(spriteSet.m_213979_(this.f_107223_));
|
||||
}
|
||||
|
||||
public void m_5744_(VertexConsumer pBuffer, Camera pRenderInfo, float pPartialTicks) {
|
||||
RenderSystem.depthMask((this.f_107230_ > 0.3f ? 1 : 0) != 0);
|
||||
super.m_5744_(pBuffer, pRenderInfo, pPartialTicks);
|
||||
RenderSystem.depthMask((boolean)true);
|
||||
}
|
||||
|
||||
public void m_5989_() {
|
||||
Vec3 direction;
|
||||
this.f_107209_ = this.f_107212_;
|
||||
this.f_107210_ = this.f_107213_;
|
||||
this.f_107211_ = this.f_107214_;
|
||||
if (this.f_107224_++ >= this.f_107225_) {
|
||||
this.m_107274_();
|
||||
return;
|
||||
}
|
||||
if (this.isHeavy) {
|
||||
this.f_107216_ = -0.04;
|
||||
}
|
||||
this.m_6257_(this.f_107215_, this.f_107216_, this.f_107217_);
|
||||
this.f_107215_ *= (double)this.f_172258_;
|
||||
this.f_107216_ *= (double)this.f_172258_;
|
||||
this.f_107217_ *= (double)this.f_172258_;
|
||||
if (this.windSpeed > 0.0f && (direction = ExplosionWindController.getWindDirection()) != Vec3.f_82478_) {
|
||||
double targetX = direction.f_82479_ * (double)this.windSpeed;
|
||||
double targetZ = direction.f_82481_ * (double)this.windSpeed;
|
||||
this.f_107215_ += (targetX - this.f_107215_) * 0.12;
|
||||
this.f_107217_ += (targetZ - this.f_107217_) * 0.12;
|
||||
}
|
||||
float lifeProgress = (float)this.f_107224_ / (float)this.f_107225_;
|
||||
this.f_107230_ = this.initialAlpha * (1.0f - lifeProgress);
|
||||
}
|
||||
|
||||
public boolean shouldCull() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public ParticleRenderType m_7556_() {
|
||||
return ParticleRenderType.f_107431_;
|
||||
}
|
||||
|
||||
public static class Provider
|
||||
implements ParticleProvider<SmokeParticleOptions> {
|
||||
private final SpriteSet sprites;
|
||||
|
||||
public Provider(SpriteSet pSprites) {
|
||||
this.sprites = pSprites;
|
||||
}
|
||||
|
||||
public Particle createParticle(SmokeParticleOptions options, ClientLevel pLevel, double pX, double pY, double pZ, double pXSpeed, double pYSpeed, double pZSpeed) {
|
||||
return new SmokeParticle(pLevel, pX, pY, pZ, pXSpeed, pYSpeed, pZSpeed, options, this.sprites);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul.client;
|
||||
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
|
||||
public final class SoundEngineAudioQueue {
|
||||
private static final Queue<Runnable> QUEUE = new ConcurrentLinkedQueue<Runnable>();
|
||||
|
||||
private SoundEngineAudioQueue() {
|
||||
}
|
||||
|
||||
public static void enqueueAudio(Runnable task) {
|
||||
if (task == null) {
|
||||
return;
|
||||
}
|
||||
if (SoundEngineAudioQueue.isSoundThread()) {
|
||||
try {
|
||||
task.run();
|
||||
}
|
||||
catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
SoundEngineAudioQueue.drainNow();
|
||||
} else {
|
||||
QUEUE.offer(task);
|
||||
}
|
||||
}
|
||||
|
||||
public static void drainNow() {
|
||||
Runnable next;
|
||||
if (!SoundEngineAudioQueue.isSoundThread()) {
|
||||
return;
|
||||
}
|
||||
while ((next = QUEUE.poll()) != null) {
|
||||
try {
|
||||
next.run();
|
||||
}
|
||||
catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isSoundThread() {
|
||||
return "Sound engine".equals(Thread.currentThread().getName());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.152.
|
||||
*/
|
||||
package com.vinlanx.explosionoverhaul.client;
|
||||
|
||||
import com.sonicether.soundphysics.SoundPhysics;
|
||||
import com.vinlanx.explosionoverhaul.client.LowPassConcussionEffect;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import net.neoforged.fml.ModList;
|
||||
import org.lwjgl.openal.AL10;
|
||||
|
||||
public class SoundPhysicsCompatibility {
|
||||
private static boolean sprLoaded = false;
|
||||
private static final Map<Integer, SprParams> sourceParams = new ConcurrentHashMap<Integer, SprParams>();
|
||||
|
||||
public static void init() {
|
||||
sprLoaded = ModList.get().isLoaded("sound_physics_remastered");
|
||||
if (sprLoaded) {
|
||||
LowPassConcussionEffect.setCompatibilityMode(true);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isCompatibilityEnabled() {
|
||||
return sprLoaded;
|
||||
}
|
||||
|
||||
public static void cacheParams(int sourceID, float sg0, float sg1, float sg2, float sg3, float sc0, float sc1, float sc2, float sc3, float dc, float dg) {
|
||||
sourceParams.put(sourceID, new SprParams(sg0, sg1, sg2, sg3, sc0, sc1, sc2, sc3, dc, dg));
|
||||
}
|
||||
|
||||
public static void onSourceStop(int sourceID) {
|
||||
sourceParams.remove(sourceID);
|
||||
}
|
||||
|
||||
public static void reapplyDirectFilterParameters() {
|
||||
if (!sprLoaded || sourceParams.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
sourceParams.entrySet().removeIf(entry -> {
|
||||
int id = (Integer)entry.getKey();
|
||||
if (!AL10.alIsSource((int)id)) {
|
||||
return true;
|
||||
}
|
||||
SprParams p = (SprParams)entry.getValue();
|
||||
try {
|
||||
SoundPhysics.setEnvironment((int)id, (float)p.sg0, (float)p.sg1, (float)p.sg2, (float)p.sg3, (float)p.sc0, (float)p.sc1, (float)p.sc2, (float)p.sc3, (float)p.dc, (float)p.dg);
|
||||
}
|
||||
catch (Throwable t) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
public static float combineGain(float sprGain) {
|
||||
return sprGain * LowPassConcussionEffect.getCurrentGainMultiplier();
|
||||
}
|
||||
|
||||
public static float combineHF(float sprHF) {
|
||||
return Math.min(sprHF, LowPassConcussionEffect.getCurrentHfMultiplier());
|
||||
}
|
||||
|
||||
private static class SprParams {
|
||||
float sg0;
|
||||
float sg1;
|
||||
float sg2;
|
||||
float sg3;
|
||||
float sc0;
|
||||
float sc1;
|
||||
float sc2;
|
||||
float sc3;
|
||||
float dc;
|
||||
float dg;
|
||||
|
||||
SprParams(float sg0, float sg1, float sg2, float sg3, float sc0, float sc1, float sc2, float sc3, float dc, float dg) {
|
||||
this.sg0 = sg0;
|
||||
this.sg1 = sg1;
|
||||
this.sg2 = sg2;
|
||||
this.sg3 = sg3;
|
||||
this.sc0 = sc0;
|
||||
this.sc1 = sc1;
|
||||
this.sc2 = sc2;
|
||||
this.sc3 = sc3;
|
||||
this.dc = dc;
|
||||
this.dg = dg;
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user