Initial commit - basic functionality

This commit is contained in:
Peter 2021-01-04 00:29:12 +08:00
commit 53af69ce43
36 changed files with 1684 additions and 0 deletions

41
.github/workflows/build.yml vendored Normal file
View File

@ -0,0 +1,41 @@
# Automatically build the project and run any configured tests for every push
# and submitted pull request. This can help catch issues that only occur on
# certain platforms or Java versions, and provides a first line of defence
# against bad commits.
name: build
on: [pull_request, push]
jobs:
build:
strategy:
matrix:
# Use these Java versions
java: [
1.8, # Minimum supported by Minecraft
11, # Current Java LTS
15 # Latest version
]
# and run on both Linux and Windows
os: [ubuntu-20.04, windows-latest]
runs-on: ${{ matrix.os }}
steps:
- name: checkout repository
uses: actions/checkout@v2
- name: validate gradle wrapper
uses: gradle/wrapper-validation-action@v1
- name: setup jdk ${{ matrix.java }}
uses: actions/setup-java@v1
with:
java-version: ${{ matrix.java }}
- name: make gradle wrapper executable
if: ${{ runner.os != 'Windows' }}
run: chmod +x ./gradlew
- name: build
run: ./gradlew build
- name: capture build artifacts
if: ${{ runner.os == 'Linux' && matrix.java == '11' }} # Only upload artifacts built from LTS java on one OS
uses: actions/upload-artifact@v2
with:
name: Artifacts
path: build/libs/

33
.gitignore vendored Normal file
View File

@ -0,0 +1,33 @@
# gradle
.gradle/
build/
out/
classes/
# eclipse
*.launch
# idea
.idea/
*.iml
*.ipr
*.iws
# vscode
.settings/
.vscode/
bin/
.classpath
.project
# macos
*.DS_Store
# fabric
run/

3
README.md Normal file
View File

@ -0,0 +1,3 @@
# Nuke mod
## In development.

82
build.gradle Normal file
View File

@ -0,0 +1,82 @@
plugins {
id 'fabric-loom' version '0.5-SNAPSHOT'
id 'maven-publish'
}
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
archivesBaseName = project.archives_base_name
version = project.mod_version
group = project.maven_group
dependencies {
// To change the versions see the gradle.properties file
minecraft "com.mojang:minecraft:${project.minecraft_version}"
mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2"
modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"
// Fabric API. This is technically optional, but you probably want it anyway.
modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"
// PSA: Some older mods, compiled on Loom 0.2.1, might have outdated Maven POMs.
// You may need to force-disable transitiveness on them.
}
processResources {
inputs.property "version", project.version
filesMatching("fabric.mod.json") {
expand "version": project.version
}
}
tasks.withType(JavaCompile).configureEach {
// ensure that the encoding is set to UTF-8, no matter what the system default is
// this fixes some edge cases with special characters not displaying correctly
// see http://yodaconditions.net/blog/fix-for-java-file-encoding-problems-with-gradle.html
// If Javadoc is generated, this must be specified in that task too.
it.options.encoding = "UTF-8"
// The Minecraft launcher currently installs Java 8 for users, so your mod probably wants to target Java 8 too
// JDK 9 introduced a new way of specifying this that will make sure no newer classes or methods are used.
// We'll use that if it's available, but otherwise we'll use the older option.
def targetVersion = 8
if (JavaVersion.current().isJava9Compatible()) {
it.options.release = targetVersion
}
}
java {
// Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task
// if it is present.
// If you remove this line, sources will not be generated.
withSourcesJar()
}
jar {
from("LICENSE") {
rename { "${it}_${project.archivesBaseName}"}
}
}
// configure the maven publication
publishing {
publications {
mavenJava(MavenPublication) {
// add all the jars that should be included when publishing to maven
artifact(remapJar) {
builtBy remapJar
}
artifact(sourcesJar) {
builtBy remapSourcesJar
}
}
}
// Select the repositories you want to publish to
// To publish to maven local, no extra repositories are necessary. Just use the task `publishToMavenLocal`.
repositories {
// See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing.
}
}

16
gradle.properties Normal file
View File

@ -0,0 +1,16 @@
# Done to increase the memory available to gradle.
org.gradle.jvmargs=-Xmx1G
# Fabric Properties
# https://modmuss50.me/fabric.html
minecraft_version=1.16.4
yarn_mappings=1.16.4+build.7
loader_version=0.10.8
#Fabric api
fabric_version=0.28.4+1.16
# Mod Properties
mod_version = 0.1.0
maven_group = io.github.npc_strider.NukeMod
archives_base_name = NukeMod

BIN
gradle/wrapper/gradle-wrapper.jar vendored Normal file

Binary file not shown.

View File

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

185
gradlew vendored Normal file
View File

@ -0,0 +1,185 @@
#!/usr/bin/env sh
#
# Copyright 2015 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin or MSYS, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=`expr $i + 1`
done
case $i in
0) set -- ;;
1) set -- "$args0" ;;
2) set -- "$args0" "$args1" ;;
3) set -- "$args0" "$args1" "$args2" ;;
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=`save "$@"`
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
exec "$JAVACMD" "$@"

89
gradlew.bat vendored Normal file
View File

@ -0,0 +1,89 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem 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%" == "0" goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

10
settings.gradle Normal file
View File

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

View File

@ -0,0 +1,47 @@
package io.github.npc_strider.NukeMod;
import io.github.npc_strider.NukeMod.fission.FissionBlock;
import io.github.npc_strider.NukeMod.fission.FissionEntity;
import net.fabricmc.api.ModInitializer;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import net.fabricmc.fabric.api.object.builder.v1.entity.FabricEntityTypeBuilder;
import net.fabricmc.fabric.api.registry.FlammableBlockRegistry;
import net.minecraft.block.Blocks;
import net.minecraft.entity.EntityDimensions;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.SpawnGroup;
import net.minecraft.item.BlockItem;
import net.minecraft.item.Item;
import net.minecraft.item.ItemGroup;
import net.minecraft.sound.SoundEvent;
import net.minecraft.util.Identifier;
import net.minecraft.util.registry.Registry;
public class NukeMod implements ModInitializer {
public static final String MOD_ID = "nuke-mod";
// public static final EntityType<FissionEntity> FISSION_ENTITY;
public static final Identifier FISSION_BLOCK_ID = new Identifier(MOD_ID, "fission-device");
public static final FissionBlock FISSION_BLOCK = new FissionBlock(FabricBlockSettings.copy(Blocks.TNT));
public static final EntityType FISSION_ENTITY_TYPE = FabricEntityTypeBuilder.create(SpawnGroup.MISC, FissionEntity::new).dimensions(new EntityDimensions(0.98F, 0.98F, false)).trackRangeBlocks(10).trackedUpdateRate(10).fireImmune().build();
public static final EntityType<FissionEntity> FISSION_ENTITY = FISSION_ENTITY_TYPE;
public static final Identifier FISSION_ALARM_ID = new Identifier(MOD_ID, "fission-alarm");
public static final Identifier FISSION_EXPLOSION_ID = new Identifier(MOD_ID, "fission-explosion");
public static SoundEvent FISSION_ALARM = new SoundEvent(FISSION_ALARM_ID);
public static SoundEvent FISSION_EXPLOSION = new SoundEvent(FISSION_EXPLOSION_ID);
@Override
public void onInitialize() {
Registry.register(Registry.BLOCK, FISSION_BLOCK_ID, FISSION_BLOCK);
Registry.register(Registry.ITEM, FISSION_BLOCK_ID, new BlockItem(FISSION_BLOCK, new Item.Settings().group(ItemGroup.REDSTONE)));
FlammableBlockRegistry.getDefaultInstance().add(FISSION_BLOCK, 15, 100); //Copy TNT settings
Registry.register(Registry.ENTITY_TYPE, new Identifier(MOD_ID, "fission-entity"), FISSION_ENTITY);
Registry.register(Registry.SOUND_EVENT, FISSION_ALARM_ID, FISSION_ALARM);
Registry.register(Registry.SOUND_EVENT, FISSION_EXPLOSION_ID, FISSION_EXPLOSION);
}
}

View File

@ -0,0 +1,45 @@
package io.github.npc_strider.NukeMod;
import io.github.npc_strider.NukeMod.client.particle.BigFookingExplosionEmitterParticle;
import io.github.npc_strider.NukeMod.client.particle.BigFookingExplosionParticle;
import io.github.npc_strider.NukeMod.client.particle.BigFookingSmokeEmitterParticle;
import io.github.npc_strider.NukeMod.client.particle.BigFookingSmokeParticle;
import io.github.npc_strider.NukeMod.client.particle.FissioningParticle;
import io.github.npc_strider.NukeMod.render.entity.FissionEntityRenderer;
import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.client.particle.v1.ParticleFactoryRegistry;
import net.fabricmc.fabric.api.client.rendereregistry.v1.EntityRendererRegistry;
import net.fabricmc.fabric.api.particle.v1.FabricParticleTypes;
import net.minecraft.particle.DefaultParticleType;
import net.minecraft.util.Identifier;
import net.minecraft.util.registry.Registry;
@Environment(EnvType.CLIENT)
public class NukeModClient implements ClientModInitializer {
public static final DefaultParticleType FISSION_PARTICLE = FabricParticleTypes.simple(false);
public static final DefaultParticleType BIG_FOOKING_EXPLOSION = FabricParticleTypes.simple(false);
public static final DefaultParticleType BIG_FOOKING_EXPLOSION_EMITTER = FabricParticleTypes.simple(false);
public static final DefaultParticleType BIG_FOOKING_SMOKE = FabricParticleTypes.simple(false);
public static final DefaultParticleType BIG_FOOKING_SMOKE_EMITTER = FabricParticleTypes.simple(false);
private static final String MOD_ID = NukeMod.MOD_ID;
@Override
public void onInitializeClient() {
Registry.register(Registry.PARTICLE_TYPE, new Identifier(MOD_ID, "fission-emission"), FISSION_PARTICLE);
Registry.register(Registry.PARTICLE_TYPE, new Identifier(MOD_ID, "big-explosion"), BIG_FOOKING_EXPLOSION);
Registry.register(Registry.PARTICLE_TYPE, new Identifier(MOD_ID, "big-explosion-emitter"), BIG_FOOKING_EXPLOSION_EMITTER);
Registry.register(Registry.PARTICLE_TYPE, new Identifier(MOD_ID, "big-smoke"), BIG_FOOKING_SMOKE);
Registry.register(Registry.PARTICLE_TYPE, new Identifier(MOD_ID, "big-smoke-emitter"), BIG_FOOKING_SMOKE_EMITTER);
ParticleFactoryRegistry.getInstance().register(FISSION_PARTICLE, FissioningParticle.Factory::new);
ParticleFactoryRegistry.getInstance().register(BIG_FOOKING_EXPLOSION, BigFookingExplosionParticle.Factory::new);
ParticleFactoryRegistry.getInstance().register(BIG_FOOKING_EXPLOSION_EMITTER, BigFookingExplosionEmitterParticle.Factory::new);
ParticleFactoryRegistry.getInstance().register(BIG_FOOKING_SMOKE, BigFookingSmokeParticle.Factory::new);
ParticleFactoryRegistry.getInstance().register(BIG_FOOKING_SMOKE_EMITTER, BigFookingSmokeEmitterParticle.Factory::new);
EntityRendererRegistry.INSTANCE.register(NukeMod.FISSION_ENTITY, (dispatcher, context) -> new FissionEntityRenderer(dispatcher));
}
}

View File

@ -0,0 +1,64 @@
package io.github.npc_strider.NukeMod.client.particle;
import io.github.npc_strider.NukeMod.NukeModClient;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.client.particle.v1.FabricSpriteProvider;
import net.minecraft.block.Material;
import net.minecraft.client.particle.NoRenderParticle;
import net.minecraft.client.particle.Particle;
import net.minecraft.client.particle.ParticleFactory;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.particle.DefaultParticleType;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
@Environment(EnvType.CLIENT)
public class BigFookingExplosionEmitterParticle extends NoRenderParticle {
private int age_;
private final int maxAge_;
private BigFookingExplosionEmitterParticle(ClientWorld world, double x, double y, double z) {
super(world, x, y, z, 0.0D, 0.0D, 0.0D);
this.maxAge_ = 10;//80;
}
public void tick() {
double r = 40.0D;
// for (int i = 0; i < (int)Math.floor(32*(float)this.age_/(float)this.maxAge_); ++i) {
for (int i = 0; i < (int)Math.floor(64/(age_+1)); ++i) {
// double d = this.x + (this.random.nextDouble() - this.random.nextDouble()) * r;
// double e = this.y + (this.random.nextDouble() - this.random.nextDouble()) * r;
// double f = this.z + (this.random.nextDouble() - this.random.nextDouble()) * r;
float alpha = this.random.nextFloat() * 360;
float beta = this.random.nextFloat() * 360;
// Vec3d position = Vec3d.fromPolar(alpha, beta).multiply((this.random.nextDouble() - this.random.nextDouble()) * r).add(this.x, this.y, this.z); //Keeps our explosion spherical, rather than in a 3d box as with the vanilla method.
double r_ = Math.sqrt(this.random.nextDouble()) * r;
Vec3d position = Vec3d.fromPolar(alpha, beta).multiply(r_).add(this.x, this.y, this.z); //Keeps our explosion spherical, rather than in a 3d box as with the vanilla method.
if (world.getBlockState(new BlockPos(position)).getMaterial() == Material.AIR) {
Vec3d v = Vec3d.fromPolar(alpha, beta).normalize().multiply(r_*0.05F+0.05F*this.random.nextFloat());
this.world.addParticle(NukeModClient.BIG_FOOKING_EXPLOSION, true, position.getX(), position.getY(), position.getZ(), v.getX(), v.getY(), v.getZ());
}
}
++this.age_;
if (this.age_ == this.maxAge_) {
this.markDead();
}
}
@Environment(EnvType.CLIENT)
public static class Factory implements ParticleFactory<DefaultParticleType> {
private final FabricSpriteProvider sprites;
public Factory(FabricSpriteProvider sprites) {
this.sprites = sprites;
}
@Override
public Particle createParticle(DefaultParticleType defaultParticleType, ClientWorld clientWorld, double d, double e, double f, double g, double h, double i) {
return new BigFookingExplosionEmitterParticle(clientWorld, d, e, f);
}
}
}

View File

@ -0,0 +1,79 @@
package io.github.npc_strider.NukeMod.client.particle;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.particle.Particle;
import net.minecraft.client.particle.ParticleFactory;
import net.minecraft.client.particle.ParticleTextureSheet;
import net.minecraft.client.particle.SpriteBillboardParticle;
import net.minecraft.client.particle.SpriteProvider;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.particle.DefaultParticleType;
@Environment(EnvType.CLIENT)
public class BigFookingExplosionParticle extends SpriteBillboardParticle {
private final SpriteProvider spriteProvider;
private final float scale_;
private BigFookingExplosionParticle(ClientWorld world, double x, double y, double z, double vx, double vy, double vz, SpriteProvider spriteProvider) {
super(world, x, y, z, vx, vy, vz);
// this.maxAge = 6 + this.random.nextInt(4);
this.maxAge = 10 + this.random.nextInt(10);
float f = this.random.nextFloat() * 0.6F + 0.4F;
this.colorRed = f;
this.colorGreen = f;
this.colorBlue = f;
this.velocityX = vx;
this.velocityY = vy;
this.velocityZ = vz;
this.prevAngle = this.angle = this.random.nextFloat()*2*(float)Math.PI;
// this.move((float)new Vec3d(vx, vy, vz).length());
// this.move(100.0F);
this.scale = this.scale_ = 15.0F*this.random.nextFloat()+20.0F; //* (1.0F - (float)d * 0.5F); //Change maximum scale factor from 2.0F to 10.0F
this.collidesWithWorld = false;
this.spriteProvider = spriteProvider;
this.setSpriteForAge(spriteProvider);
}
public int getColorMultiplier(float tint) {
return 15728880;
}
public void tick() {
this.prevPosX = this.x;
this.prevPosY = this.y;
this.prevPosZ = this.z;
if (this.age++ >= this.maxAge) {
this.markDead();
} else {
float factor = (float)age/(float)maxAge;
// this.scale = scale_*(float)(1.0F-factor);
// this.setColorAlpha(1.0F-factor*factor);
this.move(this.velocityX, this.velocityY, this.velocityZ);
// this.setColor(
// // this.random.nextFloat(), this.random.nextFloat(), this.random.nextFloat()
// (float)(1.0F-factor),
// (float)(1.0F-factor),
// (float)(1.0F-factor)
// );
this.setSpriteForAge(this.spriteProvider);
}
}
public ParticleTextureSheet getType() {
return ParticleTextureSheet.PARTICLE_SHEET_LIT;
}
@Environment(EnvType.CLIENT)
public static class Factory implements ParticleFactory<DefaultParticleType> {
private final SpriteProvider spriteProvider;
public Factory(SpriteProvider spriteProvider) {
this.spriteProvider = spriteProvider;
}
public Particle createParticle(DefaultParticleType defaultParticleType, ClientWorld clientWorld, double d, double e, double f, double g, double h, double i) {
return new BigFookingExplosionParticle(clientWorld, d, e, f, g, h, i, this.spriteProvider);
}
}
}

View File

@ -0,0 +1,81 @@
package io.github.npc_strider.NukeMod.client.particle;
import io.github.npc_strider.NukeMod.NukeModClient;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.client.particle.v1.FabricSpriteProvider;
import net.minecraft.client.particle.NoRenderParticle;
import net.minecraft.client.particle.Particle;
import net.minecraft.client.particle.ParticleFactory;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.particle.DefaultParticleType;
import net.minecraft.util.math.Vec3d;
public class BigFookingSmokeEmitterParticle extends NoRenderParticle {
private int age_;
private final int maxAge_;
private double RADIUS_X = 60;
private final float m = 1.0F;
private final int[][] radiuses = { //For the big fission cloud
{(int)Math.floor(64*m), (int)Math.floor(RADIUS_X/2) },
{(int)Math.floor(32*m), (int)Math.floor(RADIUS_X/3) },
{(int)Math.floor(16*m), (int)Math.floor(RADIUS_X/4) },
{(int)Math.floor(16*m), (int)Math.floor(RADIUS_X/5) },
{(int)Math.floor(16*m), (int)Math.floor(RADIUS_X/6) },
{(int)Math.floor(12*m), (int)Math.floor(RADIUS_X/7) },
{(int)Math.floor(8*m), (int)Math.floor(RADIUS_X/8) },
{(int)Math.floor(8*m), (int)Math.floor(RADIUS_X/9) },
{(int)Math.floor(8*m), (int)Math.floor(RADIUS_X/10) },
{(int)Math.floor(32*m), (int)Math.floor(RADIUS_X/2) },
{(int)Math.floor(32*m), (int)Math.floor(RADIUS_X/2) },
{(int)Math.floor(32*m), (int)Math.floor(RADIUS_X/2) },
{(int)Math.floor(32*m), (int)Math.floor(RADIUS_X/2.2) },
{(int)Math.floor(24*m), (int)Math.floor(RADIUS_X/2.5) },
{(int)Math.floor(16*m), (int)Math.floor(RADIUS_X/2.7) },
{(int)Math.floor(8*m), (int)Math.floor(RADIUS_X/3) },
{(int)Math.floor(8*m), (int)Math.floor(RADIUS_X/5.5) },
{(int)Math.floor(8*m), (int)Math.floor(RADIUS_X/8) },
}; // {(y+0n)=>r0,(y+1n)=>r1,(y+2n)=>r2, ... }
private BigFookingSmokeEmitterParticle(ClientWorld world, double x, double y, double z) {
super(world, x, y, z, 0.0D, 0.0D, 0.0D);
this.maxAge_ = 1;//80;
}
public void tick() {
double dy = 8.0D;
for (int j = 0; j < radiuses.length; ++j) {
for (int i = 0; i < radiuses[j][0]; ++i) {
float theta = this.random.nextFloat() * 360;
double r_ = Math.sqrt(this.random.nextDouble()) * radiuses[j][1];
Vec3d position = Vec3d.fromPolar(0, theta).multiply(r_).add(this.x, this.y+(dy*(double)(j)), this.z); //Keeps our explosion spherical, rather than in a 3d box as with the vanilla method.
// if (world.getBlockState(new BlockPos(position)).getMaterial() == Material.AIR) {
Vec3d v = Vec3d.fromPolar(0, theta).normalize().multiply(r_*0.05F+0.05F*this.random.nextFloat());
this.world.addParticle(NukeModClient.BIG_FOOKING_SMOKE, true, position.getX(), position.getY(), position.getZ(), v.getX(), v.getY()-0.25F, v.getZ());
// }
}
}
++this.age_;
if (this.age_ == this.maxAge_) {
this.markDead();
}
}
@Environment(EnvType.CLIENT)
public static class Factory implements ParticleFactory<DefaultParticleType> {
private final FabricSpriteProvider sprites;
public Factory(FabricSpriteProvider sprites) {
this.sprites = sprites;
}
@Override
public Particle createParticle(DefaultParticleType defaultParticleType, ClientWorld clientWorld, double d, double e, double f, double g, double h, double i) {
return new BigFookingSmokeEmitterParticle(clientWorld, d, e, f);
}
}
}

View File

@ -0,0 +1,33 @@
package io.github.npc_strider.NukeMod.client.particle;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.particle.AscendingParticle;
import net.minecraft.client.particle.Particle;
import net.minecraft.client.particle.ParticleFactory;
import net.minecraft.client.particle.SpriteProvider;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.particle.DefaultParticleType;
@Environment(EnvType.CLIENT)
public class BigFookingSmokeParticle extends AscendingParticle {
protected BigFookingSmokeParticle(ClientWorld world, double x, double y, double z, double velocityX, double velocityY, double velocityZ, SpriteProvider spriteProvider) {
// super(world, x, y, z, velocityX, velocityY, velocityZ, 2.5F, spriteProvider);
super(world, x, y, z, 0.1F, 0.1F, 0.1F, velocityX, velocityY, velocityZ, 1.0F, spriteProvider, 0.3F, 20*60, 0.0005D, false);
this.scale = 10.0F;
this.age = random.nextInt(160);
}
@Environment(EnvType.CLIENT)
public static class Factory implements ParticleFactory<DefaultParticleType> {
private final SpriteProvider spriteProvider;
public Factory(SpriteProvider spriteProvider) {
this.spriteProvider = spriteProvider;
}
public Particle createParticle(DefaultParticleType defaultParticleType, ClientWorld clientWorld, double d, double e, double f, double g, double h, double i) {
return new BigFookingSmokeParticle(clientWorld, d, e, f, g, h, i, this.spriteProvider);
}
}
}

View File

@ -0,0 +1,46 @@
package io.github.npc_strider.NukeMod.client.particle;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.client.particle.v1.FabricSpriteProvider;
import net.minecraft.client.particle.Particle;
import net.minecraft.client.particle.ParticleFactory;
import net.minecraft.client.particle.ParticleTextureSheet;
import net.minecraft.client.particle.SpriteBillboardParticle;
import net.minecraft.client.particle.SpriteProvider;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.particle.DefaultParticleType;
@Environment(EnvType.CLIENT)
public class FissioningParticle extends SpriteBillboardParticle {
protected FissioningParticle(ClientWorld clientWorld, double d, double e, double f, double g, double h, double i, SpriteProvider sprites) {
super(clientWorld, d, e, f, g, h, i);
setSprite(sprites.getSprite(world.random));
float j = this.random.nextFloat() * 0.3F + 0.7F;
scale(2.0F * j);
this.setMaxAge((int)(10.0F / (this.random.nextFloat() * 0.9F + 0.1F))); //Just increasing the maxAge by increasing the max from 4.0F to 10.0F
this.colorRed = 1.0F * j;
this.colorGreen = 0.0F;
this.colorBlue = 0.0F;
}
@Override
public ParticleTextureSheet getType() {
return ParticleTextureSheet.PARTICLE_SHEET_OPAQUE;
}
@Environment(EnvType.CLIENT)
public static class Factory implements ParticleFactory<DefaultParticleType> {
private final FabricSpriteProvider sprites;
public Factory(FabricSpriteProvider sprites) {
this.sprites = sprites;
}
@Override
public Particle createParticle(DefaultParticleType type, ClientWorld world, double x, double y, double z, double vX, double vY, double vZ) {
return new FissioningParticle(world, x, y, z, vX, vY, vZ, sprites);
}
}
}

View File

@ -0,0 +1,52 @@
package io.github.npc_strider.NukeMod.constant;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import net.minecraft.block.Block;
import net.minecraft.block.Blocks;
import net.minecraft.block.Material;
public class TransformConstants {
// private static final Map<Block,Block> transform = ImmutableMap.of(
// Blocks.STONE, Blocks.COBBLESTONE,
// Blocks.DIRT, Blocks.SAND,
// Blocks.GRASS_BLOCK, Blocks.SAND,
// Blocks.SAND, Blocks.GLASS
// );
// private static final Map<BlockTags,Block> transformBlockTag = ImmutableMap.of( //Nah this is dumb. Have to look up each tag (one block can have multiple tags) which consumes time.
// BlockTags.BASE_STONE_OVERWORLD, Blocks.COBBLESTONE,
// );
public static Map<Material,Block> transformMaterial; //We're using JAVA 8 so we can't use the new notation :(
static {
transformMaterial = new HashMap<>();
// transformMaterial.put( Material.STONE, Blocks.GRAVEL ); //Bad idea - creates a shitton of lag due to FallingSand entities.
// transformMaterial.put( Material.SOLID_ORGANIC, Blocks.SAND );
// transformMaterial.put( Material.SOIL, Blocks.SAND );
transformMaterial.put( Material.AGGREGATE, Blocks.GLASS );
transformMaterial.put( Material.PORTAL, Blocks.AIR );
transformMaterial.put( Material.METAL, Blocks.LAVA );
transformMaterial.put( Material.SNOW_BLOCK, Blocks.WATER );
transformMaterial.put( Material.SNOW_LAYER, Blocks.WATER );
transformMaterial.put( Material.ICE, Blocks.WATER );
transformMaterial.put( Material.DENSE_ICE, Blocks.WATER );
transformMaterial.put( Material.WOOD, Blocks.COAL_BLOCK );
transformMaterial.put( Material.NETHER_WOOD, Blocks.COAL_BLOCK );
transformMaterial.put( Material.NETHER_SHOOTS, Blocks.COAL_BLOCK );
transformMaterial.put( Material.SOLID_ORGANIC, Blocks.COAL_BLOCK );
}
public static Map<Material,List<Block>> transformToFallingTile;
static {
transformToFallingTile = new HashMap<>();
transformToFallingTile.put( Material.STONE, Arrays.asList(Blocks.GRAVEL, Blocks.COBBLESTONE) );
transformToFallingTile.put( Material.SOLID_ORGANIC, Arrays.asList(Blocks.SAND, Blocks.SANDSTONE) );
transformToFallingTile.put( Material.SOIL, Arrays.asList(Blocks.SAND, Blocks.SANDSTONE) );
}
}

View File

@ -0,0 +1,157 @@
package io.github.npc_strider.NukeMod.entity;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import io.github.npc_strider.NukeMod.NukeMod;
import io.github.npc_strider.NukeMod.NukeModClient;
import io.github.npc_strider.NukeMod.constant.TransformConstants;
import io.github.npc_strider.NukeMod.constant.TransformConstants.*;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.Material;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.damage.DamageSource;
import net.minecraft.entity.effect.StatusEffectInstance;
import net.minecraft.entity.effect.StatusEffects;
import net.minecraft.sound.SoundCategory;
import net.minecraft.sound.SoundEvents;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Box;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
public class FastExplosion {
private final Vec3d radius;
private final Vec3d effectRadius;
private final World world;
private final Vec3d origin;
private final Entity entity;
public FastExplosion(Entity entity, Vec3d radius, Vec3d effectRadius, Vec3d origin, World world) {
this.radius = radius;
this.effectRadius = effectRadius;
this.origin = origin;
this.world = world;
this.entity = entity;
}
private void removeTiles() {
double radiusX = this.radius.getX();
double radiusY = this.radius.getY();
double radiusZ = this.radius.getZ();
World wld = this.world;
for (double z = -radiusZ; z <= radiusZ; ++z) { //Note to self - don't try and parallize things...
for (double y = -radiusY; y <= radiusY; ++y) {
for (double x = -radiusX; x <= radiusX; ++x) {
Vec3d d = new Vec3d(x, y, z);
Vec3d ellipse_ = d.multiply(1/radiusZ, 1/radiusY, 1/radiusX);
double ellipseFactor = ellipse_.dotProduct(ellipse_);
BlockPos pos = new BlockPos(d.add(this.origin));
BlockState blockState = wld.getBlockState(pos);
Block block = blockState.getBlock();
// System.out.println("Position "+x+","+y+","+z+" "+ellipseFactor );
if (blockState.getMaterial() != Material.AIR && ellipseFactor < 1 && block.getBlastResistance() < 1e6) { //Barrier and Adminium has a blast resistance of 3.6e+6 -- So this is OK!
// System.out.println("Removed "+block.getName().asString() );
if (!wld.removeBlock(pos, false)) {
// System.out.println("Fluid");
wld.setBlockState(pos, Blocks.AIR.getDefaultState(), 3); //This handles fluid.
}
}
}
}
}
}
private static Map<Material,Block> transformMaterial = TransformConstants.transformMaterial;
private static Map<Material,List<Block>> transformToFallingTile = TransformConstants.transformToFallingTile;
private void effectTiles() {
double radiusX = this.effectRadius.getX();
double radiusY = this.effectRadius.getY();
double radiusZ = this.effectRadius.getZ();
World wld = this.world;
for (double z = -radiusZ; z <= radiusZ; ++z) { //Note to self - don't try and parallize things...
for (double y = -radiusY; y <= radiusY; ++y) {
for (double x = -radiusX; x <= radiusX; ++x) {
Vec3d d = new Vec3d(x, y, z);
Vec3d ellipse_ = d.multiply(1/radiusZ, 1/radiusY, 1/radiusX);
double ellipseFactor = ellipse_.dotProduct(ellipse_);
BlockPos pos = new BlockPos(d.add(this.origin));
BlockState blockState = wld.getBlockState(pos);
Block block = blockState.getBlock();
Material mat = blockState.getMaterial();
if (mat != Material.AIR && block.getBlastResistance() < 1e6 && ellipseFactor < wld.random.nextDouble() && ellipseFactor < 1) {
if (transformMaterial.containsKey(mat)) {
wld.setBlockState(pos, transformMaterial.get(mat).getDefaultState());
} else if (transformToFallingTile.containsKey(mat)) { //Prevent massive lag from creating falling entities - ensures gravity affected tiles have a solid tile beneath.
Material matBelow = wld.getBlockState(pos.down()).getMaterial();
if (matBelow != Material.AIR && matBelow != Material.AGGREGATE) {
wld.setBlockState(pos, transformToFallingTile.get(mat).get(0).getDefaultState());
} else {
wld.setBlockState(pos, transformToFallingTile.get(mat).get(1).getDefaultState());
}
} else if (mat.isBurnable() && wld.getBlockState(pos.up()).getMaterial() == Material.AIR) {
wld.setBlockState(pos.up(), Blocks.FIRE.getDefaultState());
}
//else if (transform.containsKey(block)) {
// wld.setBlockState(pos, transform.get(block).getDefaultState());
// }
}
}
}
}
}
private void damageEntities() {
List<Entity> list = this.world.getOtherEntities(this.entity, new Box(this.origin.subtract(effectRadius), this.origin.add(effectRadius)));
for (int x = 0; x < list.size(); ++x) {
Entity entity = (Entity)list.get(x);
Double distance = entity.getPos().distanceTo(this.origin);
Double effectFactor = Math.exp(-(0.01*distance)*(0.01*distance)); //IMPORTANT NOTE: We're treating all distances with the same effect falloff, but we need to use the ellipse formulae to calculate different falloffs that follow the ellipse shape.
entity.setVelocity(entity.getVelocity().add(entity.getPos().subtract(this.origin).add(0,0.2,0)).normalize().multiply(20*effectFactor)); //Knockback
if (!entity.isImmuneToExplosion() && entity.isLiving()) {
LivingEntity liveEntity = (LivingEntity)entity;
StatusEffects.POISON.applyUpdateEffect((LivingEntity)entity, 5);
// System.out.println(effectFactor);
liveEntity.damage(DamageSource.GENERIC, (float)(liveEntity.getMaxHealth()*effectFactor+2)); //Yeah, probably should use explosion damage source but whatever.
if (liveEntity.getHealth() <= 0) {
liveEntity.kill();
} else {
liveEntity.addStatusEffect(new StatusEffectInstance(StatusEffects.POISON, (int)Math.floor(120*20*effectFactor), (int)Math.ceil(5*effectFactor)));
if (!liveEntity.isFireImmune()) {
liveEntity.setFireTicks(20);
}
}
} else if (entity.getType() == EntityType.ITEM) {
int rand = this.world.random.nextInt(11);
if (rand < 8) { //20% chance of item surviving
entity.remove();
}
}
}
// List<? extends PlayerEntity> players = this.world.getPlayers(); //Was going to try some stuff with rendering a bright flash, but that seems way too hard...
// for (int x = 0; x < list.size(); ++x) {
// PlayerEntity player = players.get(x);
// }
}
public void damageBlocksAndEntities() {
if (this.world.isClient) {
//this.world.playSound(this.origin.getX(), this.origin.getY(), this.origin.getZ(), SoundEvents.ENTITY_GENERIC_EXPLODE, SoundCategory.BLOCKS, 25.0F, (1.0F + (this.world.random.nextFloat() - this.world.random.nextFloat()) * 0.2F) * 0.7F, false);
this.world.playSound(this.origin.getX(), this.origin.getY(), this.origin.getZ(), NukeMod.FISSION_EXPLOSION, SoundCategory.BLOCKS, 25.0F, (1.0F + (this.world.random.nextFloat() - this.world.random.nextFloat()) * 0.2F) * 0.7F, false);
this.world.addParticle(NukeModClient.BIG_FOOKING_EXPLOSION_EMITTER, true, this.origin.getX(), this.origin.getY(), this.origin.getZ(), 1.0D, 0.0D, 0.0D);
this.world.addParticle(NukeModClient.BIG_FOOKING_SMOKE_EMITTER, true, this.origin.getX(), this.origin.getY(), this.origin.getZ(), 1.0D, 0.0D, 0.0D);
} else {
removeTiles();
effectTiles();
damageEntities(); //Apply damage to items created to reduce lag.
}
}
}

View File

@ -0,0 +1,104 @@
package io.github.npc_strider.NukeMod.fission;
import org.jetbrains.annotations.Nullable;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.TntEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.projectile.ProjectileEntity;
// import net.minecraft.sound.SoundCategory;
// import net.minecraft.sound.SoundEvents;
import net.minecraft.text.LiteralText;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraft.world.explosion.Explosion;
public class FissionBlock extends Block { //Copying code from TntBlock because I can't override some static stuff (private static void primeTnt method)
public FissionBlock(Settings settings) {
super(settings);
}
public void onBlockAdded(BlockState state, World world, BlockPos pos, BlockState oldState, boolean notify) {
if (!oldState.isOf(state.getBlock())) {
if (world.isReceivingRedstonePower(pos)) {
primeNuke(world, pos);
world.removeBlock(pos, false);
}
}
}
public void neighborUpdate(BlockState state, World world, BlockPos pos, Block block, BlockPos fromPos, boolean notify) {
if (world.isReceivingRedstonePower(pos)) {
primeNuke(world, pos);
world.removeBlock(pos, false);
}
}
public static void primeNuke(World world, BlockPos pos) {
primeNuke(world, pos, (LivingEntity)null);
}
private static void primeNuke(World world, BlockPos pos, @Nullable LivingEntity igniter) {
if (!world.isClient) {
FissionEntity fissionEntity = new FissionEntity(world, (double)pos.getX() + 0.5D, (double)pos.getY(), (double)pos.getZ() + 0.5D, igniter);
// FissionEntity fissionEntity = NukeMod.FISSION_ENTITY.create(world).updateFissionEntity(world, (double)pos.getX() + 0.5D, (double)pos.getY(), (double)pos.getZ() + 0.5D, igniter);
world.spawnEntity(fissionEntity);
// world.playSound((PlayerEntity)null, fissionEntity.getX(), fissionEntity.getY(), fissionEntity.getZ(), SoundEvents.BLOCK_CONDUIT_ACTIVATE, SoundCategory.BLOCKS, 1.0F, 1.0F); //test audio
}
}
// Only explosive lenses
public void onDestroyedByExplosion(World world, BlockPos pos, Explosion explosion) {
if (!world.isClient) {
spawnFizzle(
world,
(double)pos.getX() + 0.5D, (double)pos.getY(), (double)pos.getZ() + 0.5D,
explosion.getCausingEntity()
);
}
}
// Only explosive lenses
public void onProjectileHit(World world, BlockState state, BlockHitResult hit, ProjectileEntity projectile) {
if (!world.isClient && projectile.isOnFire()) {
Entity entity = projectile.getOwner();
BlockPos blockPos = hit.getBlockPos();
spawnFizzle(
world,
(double)blockPos.getX() + 0.5D, (double)blockPos.getY(), (double)blockPos.getZ() + 0.5D,
entity instanceof LivingEntity ? (LivingEntity)entity : null
);
world.removeBlock(blockPos, false);
}
}
//Incomplete explosion - only explosive lenses detonate in a way that does not intiate fission
private static void spawnFizzle(World world, Double x, Double y, Double z, LivingEntity igniter) {
TntEntity tntEntity = new TntEntity(world, x, y, z, igniter);
// tntEntity.setFuse((short)(world.random.nextInt(tntEntity.getFuseTimer() / 4) + tntEntity.getFuseTimer() / 8));
tntEntity.setFuse((short)(world.random.nextInt(tntEntity.getFuseTimer() / 24) + tntEntity.getFuseTimer() / 20));
world.spawnEntity(tntEntity);
}
public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) {
if (!world.isClient) {
player.sendMessage(new LiteralText("Device ready: awaiting redstone signal . . ."), true);
}
return ActionResult.SUCCESS;
}
public boolean shouldDropItemsOnExplosion(Explosion explosion) {
return false;
}
}

View File

@ -0,0 +1,186 @@
package io.github.npc_strider.NukeMod.fission;
import org.jetbrains.annotations.Nullable;
import io.github.npc_strider.NukeMod.NukeMod;
import io.github.npc_strider.NukeMod.NukeModClient;
import io.github.npc_strider.NukeMod.entity.FastExplosion;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityDimensions;
import net.minecraft.entity.EntityPose;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.MovementType;
import net.minecraft.entity.TntEntity;
import net.minecraft.entity.data.DataTracker;
import net.minecraft.entity.data.TrackedData;
import net.minecraft.entity.data.TrackedDataHandlerRegistry;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.Packet;
import net.minecraft.network.packet.s2c.play.EntitySpawnS2CPacket;
import net.minecraft.sound.SoundCategory;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
public class FissionEntity extends Entity { // I frankly don't have time to mess about with extending TntEntity - just CTRL+C'd it
private static final int FUSE_TIMER = 20*15; //Ticks
private static final TrackedData<Integer> FUSE;
@Nullable
private LivingEntity causingEntity;
private int fuseTimer;
// private double RADIUS_X = 16;
private double RADIUS_X = 60;
private double RADIUS_Z = RADIUS_X; //Keep these the same!
// private double RADIUS_Y = 16; //I keep forgetting that minecraft vectors are weird and Z isn't the vertical axis...
private double RADIUS_Y = 96; //I keep forgetting that minecraft vectors are weird and Z isn't the vertical axis...
private Vec3d radius = new Vec3d(RADIUS_X, RADIUS_Y, RADIUS_Z);
private double EFFECT_FACTOR = 3; //This is the radius to which effects such as radiation, vaporization and glassification occur.z
private Vec3d effectRadius = new Vec3d(Math.floor(RADIUS_X*EFFECT_FACTOR), Math.floor(RADIUS_Y*EFFECT_FACTOR), Math.floor(RADIUS_Z*EFFECT_FACTOR));
// public FissionEntity(World world, double x, double y, double z, @Nullable LivingEntity igniter) {
protected FissionEntity(World world, double x, double y, double z, @Nullable LivingEntity igniter) {
this(NukeMod.FISSION_ENTITY, world);
this.updatePosition(x, y, z);
double d = world.random.nextDouble() * 6.2831854820251465D;
this.setVelocity(-Math.sin(d) * 0.02D, 0.20000000298023224D, -Math.cos(d) * 0.02D);
this.prevX = x;
this.prevY = y+5;
this.prevZ = z;
this.causingEntity = igniter;
// this(NukeMod.FISSION_ENTITY, world);
// super(world, x, y, z, igniter); //This calls the super implementation which results in the wrong tick method being used.
this.fuseTimer = FUSE_TIMER;
this.setFuse(FUSE_TIMER);
}
public FissionEntity(@Nullable EntityType<? extends FissionEntity> entityType, World world) {
super(entityType != null ? entityType : NukeMod.FISSION_ENTITY, world);
this.fuseTimer = FUSE_TIMER;
this.inanimate = true;
}
@Override
public void tick() {
if (!this.hasNoGravity()) {
this.setVelocity(this.getVelocity().add(0.0D, -0.04D, 0.0D));
}
this.move(MovementType.SELF, this.getVelocity());
this.setVelocity(this.getVelocity().multiply(0.98D));
if (this.onGround) {
this.setVelocity(this.getVelocity().multiply(0.7D, -0.5D, 0.7D));
}
--this.fuseTimer;
if (this.fuseTimer <= 0) {
this.remove();
this.explode();
// if (!this.world.isClient) {
// this.explode(new Vec3d(this.getX(), this.getY(), this.getZ()), this.RADIUS_X, this.RADIUS_Y, this.RADIUS_Z);
// }
} else {
this.updateWaterState();
// System.out.println(this.world.isClient);
if (this.world.isClient) {
double x = this.getX();
double y = this.getY();
double z = this.getZ();
Vec3d v = this.getVelocity();
double vx = v.getX();
double vy = v.getY();
double vz = v.getZ();
for (int i = 0; i < 4; i++) {
spawnAlphaParticles(x, y, z, vx, vy, vz);
}
// this.world.addParticle(ParticleTypes.SMOKE, this.getX(), this.getY() + 0.5D, this.getZ(), 0.0D, 0.0D, 0.0D);
}
if (this.fuseTimer % 60 == 0 || this.fuseTimer == FUSE_TIMER - 1) {
world.playSound((PlayerEntity)null, this.getX(), this.getY(), this.getZ(), NukeMod.FISSION_ALARM, SoundCategory.BLOCKS, 15.0F, 1.0F);
}
}
}
//Why use a custom explosion ?
//Because the vanilla method uses raytracing which works well for small explosions but does not scale to large explosions due to a limited number of rays.
//Also, raytracing is compartively more expensive/costly, which is evident by the lag generated by large explosions.
private void explode() {
//Vanilla method - small explosion // this.world.createExplosion(this, this.getX(), this.getBodyY(0.0625D), this.getZ(), 200.0F, Explosion.DestructionType.DESTROY);
FastExplosion explosion = new FastExplosion(this, radius, effectRadius, this.getPos(), this.world);
explosion.damageBlocksAndEntities();
}
private void spawnAlphaParticles(double x, double y, double z, double vx, double vy, double vz) {
this.world.addParticle(
NukeModClient.FISSION_PARTICLE,
true,
x + 0.0D + (random.nextDouble() - 0.5D) * 0.2D,
y + 0.7D + (random.nextDouble() - 0.5D) * 0.2D,
z + 0.0D + (random.nextDouble() - 0.5D) * 0.2D,
vx + (random.nextDouble() - 0.5D) * 0.25F,
vy + (random.nextDouble() - 0.0D) * 0.25F,
vz + (random.nextDouble() - 0.5D) * 0.25F
);
}
protected void initDataTracker() {
this.dataTracker.startTracking(FUSE, 80);
}
protected boolean canClimb() {
return false;
}
public boolean collides() {
return !this.removed;
}
protected void writeCustomDataToTag(CompoundTag tag) {
tag.putShort("Fuse", (short)this.getFuseTimer());
}
protected void readCustomDataFromTag(CompoundTag tag) {
this.setFuse(tag.getShort("Fuse"));
}
@Nullable
public LivingEntity getCausingEntity() {
return this.causingEntity;
}
protected float getEyeHeight(EntityPose pose, EntityDimensions dimensions) {
return 0.15F;
}
public void setFuse(int fuse) {
this.dataTracker.set(FUSE, fuse);
this.fuseTimer = fuse;
}
public void onTrackedDataSet(TrackedData<?> data) {
if (FUSE.equals(data)) {
this.fuseTimer = this.getFuse();
}
}
public int getFuse() {
return (Integer)this.dataTracker.get(FUSE);
}
public int getFuseTimer() {
return this.fuseTimer;
}
public Packet<?> createSpawnPacket() {
return new EntitySpawnS2CPacket(this);
}
static {
FUSE = DataTracker.registerData(TntEntity.class, TrackedDataHandlerRegistry.INTEGER);
}
}

View File

@ -0,0 +1,91 @@
// package io.github.npc_strider.NukeMod.mixin;
// import net.minecraft.client.network.ClientPlayNetworkHandler;
// import net.minecraft.entity.Entity;
// import net.minecraft.network.packet.s2c.play.EntitySpawnS2CPacket;
// import org.spongepowered.asm.mixin.Mixin;
// import org.spongepowered.asm.mixin.injection.At;
// import org.spongepowered.asm.mixin.injection.Inject;
// import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
// import io.github.npc_strider.NukeMod.NukeMod;
// import io.github.npc_strider.NukeMod.fission.FissionEntity;
// @Mixin(ClientPlayNetworkHandler.class)
// public class Client {
// @Inject(at = @At("TAIL"), method="onEntitySpawn")
// public void onEntitySpawn(EntitySpawnS2CPacket packet, CallbackInfo cbi) {
// System.out.l
// ClientPlayNetworkHandler cpnh = (ClientPlayNetworkHandler) (Object) this;
// if (packet.getEntityTypeId() == NukeMod.FISSION_ENTITY_TYPE) {
// Entity e = new FissionEntity(null, cpnh.getWorld());
// int i = packet.getId();
// e.updateTrackedPosition(packet.getX(), packet.getY(), packet.getZ());
// e.pitch = (float)(packet.getPitch() * 360) / 256.0F;
// e.yaw = (float)(packet.getYaw() * 360) / 256.0F;
// e.setEntityId(i);
// e.setUuid(packet.getUuid());
// cpnh.getWorld().addEntity(i, e);
// }
// }
// }
package io.github.npc_strider.NukeMod.mixin;
import net.minecraft.client.network.ClientPlayNetworkHandler;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.network.packet.s2c.play.EntitySpawnS2CPacket;
import net.minecraft.util.math.Vec3d;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
import io.github.npc_strider.NukeMod.NukeMod;
import io.github.npc_strider.NukeMod.fission.FissionEntity;
/*
Absolute bruh moment, wasted hours searching for the solution (why my non-living entity wasn't rendering/appearing on the clientside, including smoke and other effects...)
Found this solution here https://www.reddit.com/r/fabricmc/comments/g4xpm9/fabric_modding_custom_entity_rendering_on/.
The solution here https://www.reddit.com/r/fabricmc/comments/ft7ds1/entity_not_rendering/ works but it has a small (noticeable) delay until the client renders the entity,
so I'm using the first option.
*/
@Mixin(ClientPlayNetworkHandler.class)
public abstract class ClientEntityMixin {
@Shadow
private ClientWorld world;
@Inject(
method = "onEntitySpawn(Lnet/minecraft/network/packet/s2c/play/EntitySpawnS2CPacket;)V",
at = @At(value = "INVOKE_ASSIGN", target = "Lnet/minecraft/network/packet/s2c/play/EntitySpawnS2CPacket;getEntityTypeId()Lnet/minecraft/entity/EntityType;"),
cancellable = true,
locals = LocalCapture.CAPTURE_FAILHARD
)
private void onEntitySpawn(EntitySpawnS2CPacket packet, CallbackInfo ci, double x, double y, double z, EntityType<?> type) {
Entity entity = null;
if (packet.getEntityTypeId() == NukeMod.FISSION_ENTITY_TYPE) {
entity = new FissionEntity(null, world);
}
if (entity != null) {
int entityId = packet.getId();
entity.setVelocity(Vec3d.ZERO);
entity.updatePosition(x, y, z);
entity.updateTrackedPosition(x, y, z);
entity.pitch = (float) (packet.getPitch() * 360) / 256.0F;
entity.yaw = (float) (packet.getYaw() * 360) / 256.0F;
entity.setEntityId(entityId);
entity.setUuid(packet.getUuid());
this.world.addEntity(entityId, entity);
ci.cancel();
}
}
}

View File

@ -0,0 +1,59 @@
package io.github.npc_strider.NukeMod.mixin;
import java.util.Random;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import io.github.npc_strider.NukeMod.fission.FissionBlock;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.FireBlock;
import net.minecraft.block.TntBlock;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
@Mixin(FireBlock.class)
public class FireMixin {
@Shadow
private int getSpreadChance(BlockState state) {
return 0; //I think this works??
};
//private void trySpreadingFire(World world, BlockPos pos, int spreadFactor, Random rand, int currentAge) {
@Inject(
method = "trySpreadingFire(Lnet/minecraft/world/World;Lnet/minecraft/util/math/BlockPos;ILjava/util/Random;I)V",
cancellable = true,
// remap = false,
at = @At("HEAD")
)
private void trySpreadingFire(World world, BlockPos pos, int spreadFactor, Random rand, int currentAge, CallbackInfo callbackInfo) {
BlockState blockState = world.getBlockState(pos);
Block block = blockState.getBlock();
if (block instanceof FissionBlock) {
int i = this.getSpreadChance(world.getBlockState(pos));
if (rand.nextInt(spreadFactor) < i) {
TntBlock.primeTnt(world, pos); //Temporary
world.removeBlock(pos, false);
}
callbackInfo.cancel(); //Cannot just return when using inject mixin. Have to cancel first!
return;
}
};
}
//
//
//
// @Mixin(ItemStack.class) //Why the fuck does this not compile??? It's copypasted from the fucking example documentation. https://fabricmc.net/wiki/tutorial:mixin_redirectors_methods
// //y'know what, IIIIIIIIIIII give up goodbye ! -Rick Astley
// abstract class ExampleMixin {
// @Redirect(method = "readTags",
// at = @At(value = "INVOKE_ASSIGN", target = "Lnet/minecraft/item/ItemStack;fromTag(Lnet/minecraft/nbt/ListTag;)Lnet/minecraft/item/ItemStack;"))
// private static ItemStack returnNull(ListTag tag) {
// return null;
// }
// }

View File

@ -0,0 +1,54 @@
package io.github.npc_strider.NukeMod.render.entity;
import io.github.npc_strider.NukeMod.NukeMod;
import io.github.npc_strider.NukeMod.fission.FissionEntity;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.render.entity.EntityRenderDispatcher;
import net.minecraft.client.render.entity.EntityRenderer;
import net.minecraft.client.render.entity.TntMinecartEntityRenderer;
import net.minecraft.client.texture.SpriteAtlasTexture;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.client.util.math.Vector3f;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.MathHelper;
@Environment(EnvType.CLIENT)
public class FissionEntityRenderer extends EntityRenderer<FissionEntity> {
public FissionEntityRenderer(EntityRenderDispatcher entityRenderDispatcher) {
super(entityRenderDispatcher);
this.shadowRadius = 0.5F;
}
public void render(FissionEntity tntEntity, float f, float g, MatrixStack matrixStack, VertexConsumerProvider vertexConsumerProvider, int i) {
matrixStack.push();
matrixStack.translate(0.0D, 0.5D, 0.0D);
if ((float)tntEntity.getFuseTimer() - g + 1.0F < 10.0F) {
float h = 1.0F - ((float)tntEntity.getFuseTimer() - g + 1.0F) / 10.0F * 2.0F;
h = MathHelper.clamp(h, 0.0F, 1.0F);
h *= h;
h *= h;
float j = 1.0F + h * 0.3F;
matrixStack.scale(j, j, j);
}
matrixStack.multiply(Vector3f.POSITIVE_Y.getDegreesQuaternion(-90.0F));
matrixStack.translate(-0.5D, -0.5D, 0.5D);
matrixStack.multiply(Vector3f.POSITIVE_Y.getDegreesQuaternion(90.0F));
// FissionEntityRenderer.renderFlashingBlock(Blocks.WHITE_WOOL.getDefaultState(), matrixStack, vertexConsumerProvider, i, tntEntity.getFuseTimer() / 5 % 2 == 0);
TntMinecartEntityRenderer.renderFlashingBlock(NukeMod.FISSION_BLOCK.getDefaultState(), matrixStack, vertexConsumerProvider, i, tntEntity.getFuseTimer() / 5 % 2 == 0);
matrixStack.pop();
super.render(tntEntity, f, g, matrixStack, vertexConsumerProvider, i);
}
public Identifier getTexture(FissionEntity tntEntity) {
return SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE;
}
}
// MinecraftClient.getInstance().getBlockRenderManager().renderBlockAsEntity(Blocks.TNT.getDefaultState(), matrixStack, vertexConsumerProvider, i, (int)Math.floor(50*Math.sin(tntEntity.getFuseTimer())));
// System.out.println((int)Math.floor(50*Math.sin(tntEntity.getFuseTimer())));

View File

@ -0,0 +1,15 @@
{
"required": true,
"minVersion": "0.8",
"package": "io.github.npc_strider.NukeMod.mixin",
"compatibilityLevel": "JAVA_8",
"mixins": [
"FireMixin"
],
"client": [
"ClientEntityMixin"
],
"injectors": {
"defaultRequire": 1
}
}

View File

@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "minecraft:block/e"
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 453 B

View File

@ -0,0 +1 @@
{"textures" : []}

View File

@ -0,0 +1,20 @@
{
"textures": [
"minecraft:explosion_0",
"minecraft:explosion_1",
"minecraft:explosion_2",
"minecraft:explosion_3",
"minecraft:explosion_4",
"minecraft:explosion_5",
"minecraft:explosion_6",
"minecraft:explosion_7",
"minecraft:explosion_8",
"minecraft:explosion_9",
"minecraft:explosion_10",
"minecraft:explosion_11",
"minecraft:explosion_12",
"minecraft:explosion_13",
"minecraft:explosion_14",
"minecraft:explosion_15"
]
}

View File

@ -0,0 +1 @@
{"textures" : []}

View File

@ -0,0 +1,12 @@
{
"textures": [
"minecraft:generic_7",
"minecraft:generic_6",
"minecraft:generic_5",
"minecraft:generic_4",
"minecraft:generic_3",
"minecraft:generic_2",
"minecraft:generic_1",
"minecraft:generic_0"
]
}

View File

@ -0,0 +1,12 @@
{
"textures": [
"minecraft:generic_7",
"minecraft:generic_6",
"minecraft:generic_5",
"minecraft:generic_4",
"minecraft:generic_3",
"minecraft:generic_2",
"minecraft:generic_1",
"minecraft:generic_0"
]
}

View File

@ -0,0 +1,14 @@
{
"fission-alarm": {
"subtitle": "subtitles.nuke-mod.fission-alarm",
"sounds": [
"nuke-mod:fission-alarm"
]
},
"fission-explosion": {
"subtitle": "subtitles.nuke-mod.fission-explosion",
"sounds": [
"nuke-mod:fission-explosion"
]
}
}

View File

@ -0,0 +1,40 @@
{
"schemaVersion": 1,
"id": "nuke-mod",
"version": "${version}",
"name": "Yet another nuke mod",
"description": "Yet another description",
"authors": [
"npc_strider"
],
"contact": {
"homepage": "https://npc-strider.github.io/",
"sources": "https://github.com/npc-strider/NukeMod"
},
"license": "GPL-3.0",
"icon": "assets/nuke-mod/icon.png",
"environment": "*",
"entrypoints": {
"main": [
"io.github.npc_strider.NukeMod.NukeMod"
],
"client": [
"io.github.npc_strider.NukeMod.NukeModClient"
]
},
"mixins": [
"NukeMod.mixins.json"
],
"depends": {
"fabricloader": ">=0.7.4",
"fabric": "*",
"minecraft": "1.16.x"
},
"suggests": {
"another-mod": "*"
}
}