chore: format code

This commit is contained in:
LordMZTE 2023-08-29 17:39:30 +02:00
parent 5a52058f3d
commit d683e61c98
Signed by: LordMZTE
GPG key ID: B64802DC33A64FF6
232 changed files with 12816 additions and 2583 deletions

130
.clang-format Normal file
View file

@ -0,0 +1,130 @@
---
AccessModifierOffset: 0
AlignAfterOpenBracket: BlockIndent
AlignArrayOfStructures: None
AlignConsecutiveAssignments: None
AlignConsecutiveMacros: None
AlignConsecutiveBitFields: None
AlignConsecutiveDeclarations: None
AlignEscapedNewlines: DontAlign
AlignOperands: DontAlign
AlignTrailingComments: false
AllowAllArgumentsOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: Empty
AllowShortCaseLabelsOnASingleLine: false
AllowShortEnumsOnASingleLine: false
AllowShortFunctionsOnASingleLine: Empty
AllowShortIfStatementsOnASingleLine: Never
AllowShortLambdasOnASingleLine: All
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: true
AlwaysBreakTemplateDeclarations: MultiLine
AttributeMacros: []
BinPackArguments: false
BinPackParameters: false
BitFieldColonSpacing: After
BraceWrapping:
AfterCaseLabel: false
AfterClass: false
AfterControlStatement: Never
AfterEnum: false
AfterFunction: false
AfterNamespace: false
AfterStruct: false
AfterUnion: false
AfterExternBlock: false
BeforeCatch: false
BeforeElse: false
BeforeLambdaBody: false
BeforeWhile: false
IndentBraces: false
SplitEmptyFunction: false
SplitEmptyRecord: false
SplitEmptyNamespace: false
BreakAfterJavaFieldAnnotations: true
#BreakArrays: false
BreakBeforeBinaryOperators: All
BreakBeforeBraces: Custom
BreakBeforeConceptDeclarations: true
BreakBeforeTernaryOperators: true
BreakConstructorInitializers: AfterColon
BreakInheritanceList: AfterColon
BreakStringLiterals: true
ColumnLimit: 90
CompactNamespaces: false
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: false
DeriveLineEnding: false
DerivePointerAlignment: false
DisableFormat: false # wtf
EmptyLineAfterAccessModifier: Never
EmptyLineBeforeAccessModifier: Always
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: false
ForEachMacros: ["BOOST_FOREACH"]
IfMacros: []
IncludeBlocks: Regroup
IndentAccessModifiers: false
IndentCaseBlocks: false
IndentCaseLabels: true
IndentExternBlock: Indent
IndentGotoLabels: true
IndentPPDirectives: BeforeHash
#IndentRequiresClause: false
IndentWidth: 4
IndentWrappedFunctionNames: false
#InsertBraces: false
InsertTrailingCommas: Wrapped
JavaImportGroups: ["java"]
JavaScriptQuotes: Double
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: false
LambdaBodyIndentation: OuterScope
MaxEmptyLinesToKeep: 1
NamespaceIndentation: All
PackConstructorInitializers: NextLine
PointerAlignment: Left
QualifierAlignment: Left
ReferenceAlignment: Left
ReflowComments: true
#RemoveSemicolon: true
#RequiresClausePosition: OwnLine
#RequiresExpressionIndentation: OuterScope
SeparateDefinitionBlocks: Always
SortIncludes: CaseInsensitive
SortJavaStaticImport: Before
SortUsingDeclarations: true
SpaceAfterCStyleCast: true
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: false
SpaceAroundPointerQualifiers: After
SpaceBeforeAssignmentOperators: true
SpaceBeforeCaseColon: false
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: false
SpaceBeforeInheritanceColon: false
SpaceBeforeParens: ControlStatementsExceptControlMacros
SpaceBeforeRangeBasedForLoopColon: true
SpaceBeforeSquareBrackets: false
SpaceInEmptyBlock: false
SpaceInEmptyParentheses: false
SpacesInAngles: Never
SpacesInCStyleCastParentheses: false
SpacesInConditionalStatement: false
SpacesInContainerLiterals: false
SpacesInLineCommentPrefix:
Minimum: 0
Maximum: -1
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: c++20
StatementAttributeLikeMacros: []
StatementMacros: []
TabWidth: 4
TypenameMacros: []
UseCRLF: false # wtf
UseTab: Never
WhitespaceSensitiveMacros: ["BOOST_PP_STRINGSIZE"]

View file

@ -14,14 +14,14 @@ import com.cursedcauldron.wildbackport.common.registry.WBGameRules;
import com.cursedcauldron.wildbackport.common.registry.WBItems;
import com.cursedcauldron.wildbackport.common.registry.WBMobEffects;
import com.cursedcauldron.wildbackport.common.registry.WBPositionSources;
import com.cursedcauldron.wildbackport.common.registry.worldgen.WBFeatures;
import com.cursedcauldron.wildbackport.common.registry.worldgen.RootPlacerType;
import com.cursedcauldron.wildbackport.common.registry.worldgen.WBTreeDecorators;
import com.cursedcauldron.wildbackport.common.registry.worldgen.WBTrunkPlacers;
import com.cursedcauldron.wildbackport.common.registry.entity.WBActivities;
import com.cursedcauldron.wildbackport.common.registry.entity.WBEntityTypes;
import com.cursedcauldron.wildbackport.common.registry.entity.WBMemoryModules;
import com.cursedcauldron.wildbackport.common.registry.entity.WBSensorTypes;
import com.cursedcauldron.wildbackport.common.registry.worldgen.RootPlacerType;
import com.cursedcauldron.wildbackport.common.registry.worldgen.WBFeatures;
import com.cursedcauldron.wildbackport.common.registry.worldgen.WBTreeDecorators;
import com.cursedcauldron.wildbackport.common.registry.worldgen.WBTrunkPlacers;
import com.cursedcauldron.wildbackport.common.tag.InstrumentTags;
import com.cursedcauldron.wildbackport.common.tag.WBBiomeTags;
import com.cursedcauldron.wildbackport.common.tag.WBBlockTags;
@ -72,8 +72,11 @@ public class WildBackport {
WBItemTags.TAGS.bootstrap();
InstrumentTags.TAGS.bootstrap();
// ItemProperties.register(WBItems.RECOVERY_COMPASS.get(), new ResourceLocation("angle"), new CompassItemPropertyFunction((level, stack, entity) -> {
// return entity instanceof Player player ? Recovery.of(player).getLastDeathLocation().orElse(null) : null;
// }));
// ItemProperties.register(WBItems.RECOVERY_COMPASS.get(), new
// ResourceLocation("angle"), new CompassItemPropertyFunction((level,
// stack, entity) -> {
// return entity instanceof Player player ?
// Recovery.of(player).getLastDeathLocation().orElse(null) : null;
// }));
}
}

View file

@ -41,28 +41,58 @@ public class ClientSetup {
*/
public static void onClient() {
// Colors
ColorRegistry.register((state, getter, pos, tint) -> (getter == null || pos == null) ? FoliageColor.getDefaultColor() : BiomeColors.getAverageFoliageColor(getter, pos), WBBlocks.MANGROVE_LEAVES);
ColorRegistry.register(
(state, getter, pos, tint)
-> (getter == null || pos == null)
? FoliageColor.getDefaultColor()
: BiomeColors.getAverageFoliageColor(getter, pos),
WBBlocks.MANGROVE_LEAVES
);
ColorRegistry.register((stack, tint) -> 9619016, WBBlocks.MANGROVE_LEAVES);
// Entity Renderers
RenderRegistry.setLayerDefinition(AllayRenderer.MODEL_LAYER, AllayModel::createBodyLayer);
RenderRegistry.setLayerDefinition(
AllayRenderer.MODEL_LAYER, AllayModel::createBodyLayer
);
RenderRegistry.setEntityRender(WBEntityTypes.ALLAY, AllayRenderer::new);
RenderRegistry.setLayerDefinition(WardenRenderer.MODEL_LAYER, WardenModel::createBodyLayer);
RenderRegistry.setLayerDefinition(
WardenRenderer.MODEL_LAYER, WardenModel::createBodyLayer
);
RenderRegistry.setEntityRender(WBEntityTypes.WARDEN, WardenRenderer::new);
RenderRegistry.setLayerDefinition(FrogRenderer.MODEL_LAYER, FrogModel::createBodyLayer);
RenderRegistry.setLayerDefinition(
FrogRenderer.MODEL_LAYER, FrogModel::createBodyLayer
);
RenderRegistry.setEntityRender(WBEntityTypes.FROG, FrogRenderer::new);
RenderRegistry.setLayerDefinition(TadpoleRenderer.MODEL_LAYER, TadpoleModel::createBodyLayer);
RenderRegistry.setLayerDefinition(
TadpoleRenderer.MODEL_LAYER, TadpoleModel::createBodyLayer
);
RenderRegistry.setEntityRender(WBEntityTypes.TADPOLE, TadpoleRenderer::new);
for (Boat.Type type : Boat.Type.values()) RenderRegistry.setLayerDefinition(ChestBoatModel.createChestBoat(type), () -> ChestBoatModel.createBodyModel(true));
RenderRegistry.setEntityRender(WBEntityTypes.MANGROVE_BOAT, context -> new ChestBoatRenderer(context, false));
RenderRegistry.setEntityRender(WBEntityTypes.CHEST_BOAT, context -> new ChestBoatRenderer(context, true));
for (Boat.Type type : Boat.Type.values())
RenderRegistry.setLayerDefinition(
ChestBoatModel.createChestBoat(type),
() -> ChestBoatModel.createBodyModel(true)
);
RenderRegistry.setEntityRender(
WBEntityTypes.MANGROVE_BOAT, context -> new ChestBoatRenderer(context, false)
);
RenderRegistry.setEntityRender(
WBEntityTypes.CHEST_BOAT, context -> new ChestBoatRenderer(context, true)
);
// Particle Renderers
ParticleRegistry.create(WBParticleTypes.SCULK_SOUL, SculkSoulParticle.Provider::new);
ParticleRegistry.create(WBParticleTypes.SCULK_CHARGE, SculkChargeParticle.Provider::new);
ParticleRegistry.create(WBParticleTypes.SCULK_CHARGE_POP, SculkChargePopParticle.Provider::new);
ParticleRegistry.create(
WBParticleTypes.SCULK_SOUL, SculkSoulParticle.Provider::new
);
ParticleRegistry.create(
WBParticleTypes.SCULK_CHARGE, SculkChargeParticle.Provider::new
);
ParticleRegistry.create(
WBParticleTypes.SCULK_CHARGE_POP, SculkChargePopParticle.Provider::new
);
ParticleRegistry.create(WBParticleTypes.SHRIEK, ShriekParticle.Provider::new);
ParticleRegistry.create(WBParticleTypes.SONIC_BOOM, SonicBoomParticle.Provider::new);
ParticleRegistry.create(
WBParticleTypes.SONIC_BOOM, SonicBoomParticle.Provider::new
);
}
/**
@ -70,14 +100,15 @@ public class ClientSetup {
*/
public static void onPostClient() {
// Block Render Types
RenderRegistry.setBlockRenderType(RenderType.cutout(),
WBBlocks.SCULK_VEIN.get(),
WBBlocks.SCULK_SHRIEKER.get(),
WBBlocks.FROGSPAWN.get(),
WBBlocks.MANGROVE_ROOTS.get(),
WBBlocks.MANGROVE_TRAPDOOR.get(),
WBBlocks.MANGROVE_PROPAGULE.get(),
WBBlocks.POTTED_MANGROVE_PROPAGULE.get()
RenderRegistry.setBlockRenderType(
RenderType.cutout(),
WBBlocks.SCULK_VEIN.get(),
WBBlocks.SCULK_SHRIEKER.get(),
WBBlocks.FROGSPAWN.get(),
WBBlocks.MANGROVE_ROOTS.get(),
WBBlocks.MANGROVE_TRAPDOOR.get(),
WBBlocks.MANGROVE_PROPAGULE.get(),
WBBlocks.POTTED_MANGROVE_PROPAGULE.get()
);
}
}

File diff suppressed because one or more lines are too long

View file

@ -1,5 +1,8 @@
package com.cursedcauldron.wildbackport.client.animation.api;
import java.util.Optional;
import java.util.function.Function;
import com.cursedcauldron.wildbackport.core.mixin.access.ModelPartAccessor;
import com.mojang.math.Vector3f;
import net.fabricmc.api.EnvType;
@ -10,9 +13,6 @@ import net.minecraft.client.renderer.RenderType;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.Entity;
import java.util.Optional;
import java.util.function.Function;
//<>
@Environment(EnvType.CLIENT)
@ -28,15 +28,31 @@ public abstract class AnimatedModel<E extends Entity> extends HierarchicalModel<
}
public Optional<ModelPart> getChild(String name) {
return this.root().getAllParts().filter(part -> ((ModelPartAccessor)(Object)part).getChildren().containsKey(name)).findFirst().map(part -> part.getChild(name));
return this.root()
.getAllParts()
.filter(
part
-> ((ModelPartAccessor) (Object) part).getChildren().containsKey(name)
)
.findFirst()
.map(part -> part.getChild(name));
}
protected void animate(AnimationState state, Animation animation, float animationProgress) {
protected void
animate(AnimationState state, Animation animation, float animationProgress) {
this.animate(state, animation, animationProgress, 1.0F);
}
protected void animate(AnimationState animationState, Animation animation, float animationProgress, float speedMultiplier) {
protected void animate(
AnimationState animationState,
Animation animation,
float animationProgress,
float speedMultiplier
) {
animationState.run(animationProgress, speedMultiplier);
animationState.run(state -> AnimationHelper.animate(this, animation, state.runningTime(), 1.0F, CACHE));
animationState.run(
state
-> AnimationHelper.animate(this, animation, state.runningTime(), 1.0F, CACHE)
);
}
}

View file

@ -1,18 +1,23 @@
package com.cursedcauldron.wildbackport.client.animation.api;
import java.util.List;
import java.util.Map;
import com.google.common.collect.Maps;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import org.apache.commons.compress.utils.Lists;
import java.util.List;
import java.util.Map;
@Environment(EnvType.CLIENT)
public record Animation(float lengthInSeconds, boolean looping, Map<String, List<Transformation>> boneAnimations) {
public record Animation(
float lengthInSeconds,
boolean looping,
Map<String, List<Transformation>> boneAnimations
) {
public static class Builder {
private final float lengthInSeconds;
private final Map<String, List<Transformation>> transformations = Maps.newHashMap();
private final Map<String, List<Transformation>> transformations
= Maps.newHashMap();
private boolean looping;
public static Builder create(float lengthInSeconds) {
@ -29,12 +34,15 @@ public record Animation(float lengthInSeconds, boolean looping, Map<String, List
}
public Builder addBoneAnimation(String name2, Transformation transformation) {
this.transformations.computeIfAbsent(name2, name -> Lists.newArrayList()).add(transformation);
this.transformations.computeIfAbsent(name2, name -> Lists.newArrayList())
.add(transformation);
return this;
}
public Animation build() {
return new Animation(this.lengthInSeconds, this.looping, this.transformations);
return new Animation(
this.lengthInSeconds, this.looping, this.transformations
);
}
}
}

View file

@ -1,41 +1,59 @@
package com.cursedcauldron.wildbackport.client.animation.api;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import com.mojang.math.Vector3f;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.model.geom.ModelPart;
import net.minecraft.util.Mth;
import java.util.List;
import java.util.Map;
import java.util.Optional;
//<>
@Environment(EnvType.CLIENT)
public class AnimationHelper {
public static void animate(AnimatedModel<?> model, Animation animation, long runningTime, float speed, Vector3f cache) {
public static void animate(
AnimatedModel<?> model,
Animation animation,
long runningTime,
float speed,
Vector3f cache
) {
float runningSeconds = getRunningSeconds(animation, runningTime);
for (Map.Entry<String, List<Transformation>> animations : animation.boneAnimations().entrySet()) {
for (Map.Entry<String, List<Transformation>> animations :
animation.boneAnimations().entrySet()) {
Optional<ModelPart> modelPart = model.getChild(animations.getKey());
List<Transformation> transformations = animations.getValue();
modelPart.ifPresent(part -> transformations.forEach(transformation -> {
Keyframe[] keyframes = transformation.keyframes();
int start = Math.max(0, Mth.binarySearch(0, keyframes.length, i -> runningSeconds <= keyframes[i].timestamp()) - 1);
int start = Math.max(
0,
Mth.binarySearch(
0,
keyframes.length,
i -> runningSeconds <= keyframes[i].timestamp()
) - 1
);
int end = Math.min(keyframes.length - 1, start + 1);
Keyframe frameStart = keyframes[start];
Keyframe frameEnd = keyframes[end];
float current = runningSeconds - frameStart.timestamp();
float delta = Mth.clamp(current / (frameEnd.timestamp() - frameStart.timestamp()), 0.0f, 1.0f);
frameEnd.interpolation().apply(cache, delta, keyframes, start, end, speed);
float delta = Mth.clamp(
current / (frameEnd.timestamp() - frameStart.timestamp()), 0.0f, 1.0f
);
frameEnd.interpolation().apply(
cache, delta, keyframes, start, end, speed
);
transformation.target().apply(part, cache);
}));
}
}
private static float getRunningSeconds(Animation animation, long runningTime) {
float time = (float)runningTime / 1000.0f;
float time = (float) runningTime / 1000.0f;
return animation.looping() ? time % animation.lengthInSeconds() : time;
}
@ -44,10 +62,14 @@ public class AnimationHelper {
}
public static Vector3f rotation(float x, float y, float z) {
return new Vector3f(x * ((float)Math.PI / 180), y * ((float)Math.PI / 180), z * ((float)Math.PI / 180));
return new Vector3f(
x * ((float) Math.PI / 180),
y * ((float) Math.PI / 180),
z * ((float) Math.PI / 180)
);
}
public static Vector3f scale(double x, double y, double z) {
return new Vector3f((float)(x - 1.0), (float)(y - 1.0), (float)(z - 1.0));
return new Vector3f((float) (x - 1.0), (float) (y - 1.0), (float) (z - 1.0));
}
}

View file

@ -1,9 +1,9 @@
package com.cursedcauldron.wildbackport.client.animation.api;
import net.minecraft.util.Mth;
import java.util.function.Consumer;
import net.minecraft.util.Mth;
//<>
public class AnimationState {
@ -11,12 +11,13 @@ public class AnimationState {
private long runningTime;
public void start(int ticks) {
this.startedAt = (long)ticks * 1000L / 20L;
this.startedAt = (long) ticks * 1000L / 20L;
this.runningTime = 0L;
}
public void startIfNotRunning(int ticks) {
if (!this.isRunning()) this.start(ticks);
if (!this.isRunning())
this.start(ticks);
}
public void stop() {
@ -24,13 +25,15 @@ public class AnimationState {
}
public void run(Consumer<AnimationState> consumer) {
if (this.isRunning()) consumer.accept(this);
if (this.isRunning())
consumer.accept(this);
}
public void run(float animationProgress, float speedMultiplier) {
if (this.isRunning()) {
long runningAt = Mth.lfloor(animationProgress * 1000.0F / 20.0F);
this.runningTime += (long)((float)(runningAt - this.startedAt) * speedMultiplier);
this.runningTime
+= (long) ((float) (runningAt - this.startedAt) * speedMultiplier);
this.startedAt = runningAt;
}
}

View file

@ -5,4 +5,5 @@ import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
@Environment(EnvType.CLIENT)
public record Keyframe(float timestamp, Vector3f target, Transformation.Interpolation interpolation) {}
public record
Keyframe(float timestamp, Vector3f target, Transformation.Interpolation interpolation) {}

View file

@ -14,29 +14,65 @@ public record Transformation(Target target, Keyframe... keyframes) {
}
public static class Interpolations {
public static final Interpolation LINEAL = (cache, delta, keyframes, start, end, speed) -> {
public static final Interpolation LINEAL
= (cache, delta, keyframes, start, end, speed) -> {
Vector3f frameStart = keyframes[start].target();
Vector3f frameEnd = keyframes[end].target();
cache.set(Mth.lerp(delta, frameStart.x(), frameEnd.x()) * speed, Mth.lerp(delta, frameStart.y(), frameEnd.y()) * speed, Mth.lerp(delta, frameStart.z(), frameEnd.z()) * speed);
cache.set(
Mth.lerp(delta, frameStart.x(), frameEnd.x()) * speed,
Mth.lerp(delta, frameStart.y(), frameEnd.y()) * speed,
Mth.lerp(delta, frameStart.z(), frameEnd.z()) * speed
);
return cache;
};
public static final Interpolation CATMULL = (cache, delta, keyframes, start, end, speed) -> {
public static final Interpolation CATMULL
= (cache, delta, keyframes, start, end, speed) -> {
Vector3f frameStartPoint = keyframes[Math.max(0, start - 1)].target();
Vector3f frameStart = keyframes[start].target();
Vector3f frameEnd = keyframes[end].target();
Vector3f frameEndPoint = keyframes[Math.min(keyframes.length - 1, end + 1)].target();
cache.set(MathUtils.catmullrom(delta, frameStartPoint.x(), frameStart.x(), frameEnd.x(), frameEndPoint.x()) * speed, MathUtils.catmullrom(delta, frameStartPoint.y(), frameStart.y(), frameEnd.y(), frameEndPoint.y()) * speed, MathUtils.catmullrom(delta, frameStartPoint.z(), frameStart.z(), frameEnd.z(), frameEndPoint.z()) * speed);
Vector3f frameEndPoint
= keyframes[Math.min(keyframes.length - 1, end + 1)].target();
cache.set(
MathUtils.catmullrom(
delta,
frameStartPoint.x(),
frameStart.x(),
frameEnd.x(),
frameEndPoint.x()
) * speed,
MathUtils.catmullrom(
delta,
frameStartPoint.y(),
frameStart.y(),
frameEnd.y(),
frameEndPoint.y()
) * speed,
MathUtils.catmullrom(
delta,
frameStartPoint.z(),
frameStart.z(),
frameEnd.z(),
frameEndPoint.z()
) * speed
);
return cache;
};
}
public static class Targets {
public static final Target TRANSLATE = Animated::translate;
public static final Target ROTATE = Animated::rotate;
public static final Target SCALE = Animated::scaleY;
public static final Target TRANSLATE = Animated::translate;
public static final Target ROTATE = Animated::rotate;
public static final Target SCALE = Animated::scaleY;
}
public interface Interpolation {
Vector3f apply(Vector3f cache, float delta, Keyframe[] keyframes, int start, int end, float speed);
Vector3f apply(
Vector3f cache,
float delta,
Keyframe[] keyframes,
int start,
int end,
float speed
);
}
}

View file

@ -13,7 +13,16 @@ import net.minecraft.client.particle.TextureSheetParticle;
public class SculkChargeParticle extends TextureSheetParticle {
private final SpriteSet sprites;
public SculkChargeParticle(ClientLevel level, double x, double y, double z, double xMotion, double yMotion, double zMotion, SpriteSet sprites) {
public SculkChargeParticle(
ClientLevel level,
double x,
double y,
double z,
double xMotion,
double yMotion,
double zMotion,
SpriteSet sprites
) {
super(level, x, y, z, xMotion, yMotion, zMotion);
this.sprites = sprites;
this.friction = 0.96F;
@ -38,10 +47,22 @@ public class SculkChargeParticle extends TextureSheetParticle {
this.setSpriteFromAge(this.sprites);
}
public record Provider(SpriteSet sprites) implements ParticleProvider<SculkChargeParticleOptions> {
public record Provider(SpriteSet sprites)
implements ParticleProvider<SculkChargeParticleOptions> {
@Override
public Particle createParticle(SculkChargeParticleOptions options, ClientLevel level, double x, double y, double z, double xMotion, double yMotion, double zMotion) {
SculkChargeParticle particle = new SculkChargeParticle(level, x, y, z, xMotion, yMotion, zMotion, this.sprites);
public Particle createParticle(
SculkChargeParticleOptions options,
ClientLevel level,
double x,
double y,
double z,
double xMotion,
double yMotion,
double zMotion
) {
SculkChargeParticle particle = new SculkChargeParticle(
level, x, y, z, xMotion, yMotion, zMotion, this.sprites
);
particle.setAlpha(1.0F);
particle.setParticleSpeed(xMotion, yMotion, zMotion);
particle.oRoll = particle.roll = options.roll();

View file

@ -1,5 +1,7 @@
package com.cursedcauldron.wildbackport.client.particle;
import java.util.Locale;
import com.cursedcauldron.wildbackport.client.registry.WBParticleTypes;
import com.mojang.brigadier.StringReader;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
@ -10,26 +12,32 @@ import net.minecraft.core.particles.ParticleOptions;
import net.minecraft.core.particles.ParticleType;
import net.minecraft.network.FriendlyByteBuf;
import java.util.Locale;
public record SculkChargeParticleOptions(float roll) implements ParticleOptions {
public static final Codec<SculkChargeParticleOptions> CODEC = RecordCodecBuilder.create(instance -> {
return instance.group(Codec.FLOAT.fieldOf("roll").forGetter(options -> {
return options.roll;
})).apply(instance, SculkChargeParticleOptions::new);
});
public static final Codec<SculkChargeParticleOptions> CODEC
= RecordCodecBuilder.create(instance -> {
return instance
.group(Codec.FLOAT.fieldOf("roll").forGetter(options -> {
return options.roll;
}))
.apply(instance, SculkChargeParticleOptions::new);
});
public static final Deserializer<SculkChargeParticleOptions> DESERIALIZER = new Deserializer<>() {
@Override
public SculkChargeParticleOptions fromCommand(ParticleType<SculkChargeParticleOptions> type, StringReader reader) throws CommandSyntaxException {
return new SculkChargeParticleOptions(reader.readFloat());
}
public static final Deserializer<SculkChargeParticleOptions> DESERIALIZER
= new Deserializer<>() {
@Override
public SculkChargeParticleOptions fromCommand(
ParticleType<SculkChargeParticleOptions> type, StringReader reader
) throws CommandSyntaxException {
return new SculkChargeParticleOptions(reader.readFloat());
}
@Override
public SculkChargeParticleOptions fromNetwork(ParticleType<SculkChargeParticleOptions> type, FriendlyByteBuf buf) {
return new SculkChargeParticleOptions(buf.readFloat());
}
};
@Override
public SculkChargeParticleOptions fromNetwork(
ParticleType<SculkChargeParticleOptions> type, FriendlyByteBuf buf
) {
return new SculkChargeParticleOptions(buf.readFloat());
}
};
@Override
public ParticleType<?> getType() {
@ -43,6 +51,11 @@ public record SculkChargeParticleOptions(float roll) implements ParticleOptions
@Override
public String writeToString() {
return String.format(Locale.ROOT, "%s %.2f", Registry.PARTICLE_TYPE.getId(this.getType()), this.roll);
return String.format(
Locale.ROOT,
"%s %.2f",
Registry.PARTICLE_TYPE.getId(this.getType()),
this.roll
);
}
}

View file

@ -16,7 +16,16 @@ import net.minecraft.core.particles.SimpleParticleType;
public class SculkChargePopParticle extends TextureSheetParticle {
private final SpriteSet sprites;
public SculkChargePopParticle(ClientLevel level, double x, double y, double z, double xMotion, double yMotion, double zMotion, SpriteSet sprites) {
public SculkChargePopParticle(
ClientLevel level,
double x,
double y,
double z,
double xMotion,
double yMotion,
double zMotion,
SpriteSet sprites
) {
super(level, x, y, z, xMotion, yMotion, zMotion);
this.sprites = sprites;
this.friction = 0.96F;
@ -41,10 +50,22 @@ public class SculkChargePopParticle extends TextureSheetParticle {
this.setSpriteFromAge(this.sprites);
}
public record Provider(SpriteSet sprites) implements ParticleProvider<SimpleParticleType> {
public record Provider(SpriteSet sprites)
implements ParticleProvider<SimpleParticleType> {
@Override
public Particle createParticle(SimpleParticleType type, ClientLevel level, double x, double y, double z, double xMotion, double yMotion, double zMotion) {
SculkChargePopParticle particle = new SculkChargePopParticle(level, x, y, z, xMotion, yMotion, zMotion, this.sprites);
public Particle createParticle(
SimpleParticleType type,
ClientLevel level,
double x,
double y,
double z,
double xMotion,
double yMotion,
double zMotion
) {
SculkChargePopParticle particle = new SculkChargePopParticle(
level, x, y, z, xMotion, yMotion, zMotion, this.sprites
);
particle.setAlpha(1.0F);
particle.setParticleSpeed(xMotion, yMotion, zMotion);
particle.setLifetime(level.getRandom().nextInt(4) + 6);

View file

@ -16,7 +16,16 @@ import net.minecraft.core.particles.SimpleParticleType;
public class SculkSoulParticle extends RisingParticle {
private final SpriteSet sprites;
public SculkSoulParticle(ClientLevel level, double x, double y, double z, double xMotion, double yMotion, double zMotion, SpriteSet sprites) {
public SculkSoulParticle(
ClientLevel level,
double x,
double y,
double z,
double xMotion,
double yMotion,
double zMotion,
SpriteSet sprites
) {
super(level, x, y, z, xMotion, yMotion, zMotion);
this.sprites = sprites;
this.getQuadSize(1.5F);
@ -40,10 +49,22 @@ public class SculkSoulParticle extends RisingParticle {
}
@Environment(EnvType.CLIENT)
public record Provider(SpriteSet sprites) implements ParticleProvider<SimpleParticleType> {
public record Provider(SpriteSet sprites)
implements ParticleProvider<SimpleParticleType> {
@Override
public Particle createParticle(SimpleParticleType type, ClientLevel level, double x, double y, double z, double xMotion, double yMotion, double zMotion) {
SculkSoulParticle particle = new SculkSoulParticle(level, x, y, z, xMotion, yMotion, zMotion, this.sprites);
public Particle createParticle(
SimpleParticleType type,
ClientLevel level,
double x,
double y,
double z,
double xMotion,
double yMotion,
double zMotion
) {
SculkSoulParticle particle = new SculkSoulParticle(
level, x, y, z, xMotion, yMotion, zMotion, this.sprites
);
particle.setAlpha(1.0F);
return particle;
}

View file

@ -1,5 +1,7 @@
package com.cursedcauldron.wildbackport.client.particle;
import java.util.function.Consumer;
import com.mojang.blaze3d.vertex.VertexConsumer;
import com.mojang.math.Quaternion;
import com.mojang.math.Vector3f;
@ -14,10 +16,9 @@ import net.minecraft.client.particle.TextureSheetParticle;
import net.minecraft.util.Mth;
import net.minecraft.world.phys.Vec3;
import java.util.function.Consumer;
public class ShriekParticle extends TextureSheetParticle {
private static final Vector3f AXIS = Util.make(new Vector3f(0.5F, 0.5F, 0.5F), Vector3f::normalize);
private static final Vector3f AXIS
= Util.make(new Vector3f(0.5F, 0.5F, 0.5F), Vector3f::normalize);
private static final Vector3f OFFSET = new Vector3f(-1.0F, -1.0F, 0.0F);
private int delay;
@ -34,32 +35,47 @@ public class ShriekParticle extends TextureSheetParticle {
@Override
public float getQuadSize(float tickDelta) {
return this.quadSize * Mth.clamp(((float)this.age + tickDelta) / (float)this.lifetime * 0.75F, 0.0F, 1.0F);
return this.quadSize
* Mth.clamp(
((float) this.age + tickDelta) / (float) this.lifetime * 0.75F, 0.0F, 1.0F
);
}
@Override
public void render(VertexConsumer vertex, Camera camera, float tickDelta) {
if (this.delay > 0) return;
this.alpha = 1.0F - Mth.clamp(((float)this.age + tickDelta) / (float)this.lifetime * 0.75F, 0.0F, 1.0F);
if (this.delay > 0)
return;
this.alpha = 1.0F
- Mth.clamp(
((float) this.age + tickDelta) / (float) this.lifetime * 0.75F, 0.0F, 1.0F
);
this.render(vertex, camera, tickDelta, quaternion -> {
quaternion.mul(Vector3f.YP.rotation(0.0F));
quaternion.mul(Vector3f.XP.rotation(-1.0472F));
});
this.render(vertex, camera, tickDelta, quaternion -> {
quaternion.mul(Vector3f.YP.rotation((float)(-Math.PI)));
quaternion.mul(Vector3f.YP.rotation((float) (-Math.PI)));
quaternion.mul(Vector3f.XP.rotation(1.0472F));
});
}
private void render(VertexConsumer vertex, Camera camera, float tickDelta, Consumer<Quaternion> consumer) {
private void render(
VertexConsumer vertex,
Camera camera,
float tickDelta,
Consumer<Quaternion> consumer
) {
Vec3 pos = camera.getPosition();
float x = (float)(Mth.lerp(tickDelta, this.xo, this.x) - pos.x());
float y = (float)(Mth.lerp(tickDelta, this.yo, this.y) - pos.y());
float z = (float)(Mth.lerp(tickDelta, this.zo, this.z) - pos.z());
float x = (float) (Mth.lerp(tickDelta, this.xo, this.x) - pos.x());
float y = (float) (Mth.lerp(tickDelta, this.yo, this.y) - pos.y());
float z = (float) (Mth.lerp(tickDelta, this.zo, this.z) - pos.z());
Quaternion quaternion = new Quaternion(AXIS, 0.0F, true);
consumer.accept(quaternion);
OFFSET.transform(quaternion);
Vector3f[] vectors = 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)};
Vector3f[] vectors = 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 quadSize = this.getQuadSize(tickDelta);
for (int i = 0; i < 4; i++) {
@ -74,11 +90,15 @@ public class ShriekParticle extends TextureSheetParticle {
this.addVertex(vertex, vectors[1], this.getU1(), this.getV0(), light);
this.addVertex(vertex, vectors[2], this.getU0(), this.getV0(), light);
this.addVertex(vertex, vectors[3], this.getU0(), this.getV1(), light);
}
private void addVertex(VertexConsumer vertex, Vector3f vector, float u, float v, int light) {
vertex.vertex(vector.x(), vector.y(), vector.z()).uv(u, v).color(this.rCol, this.gCol, this.bCol, this.alpha).uv2(light).endVertex();
private void
addVertex(VertexConsumer vertex, Vector3f vector, float u, float v, int light) {
vertex.vertex(vector.x(), vector.y(), vector.z())
.uv(u, v)
.color(this.rCol, this.gCol, this.bCol, this.alpha)
.uv2(light)
.endVertex();
}
@Override
@ -100,9 +120,19 @@ public class ShriekParticle extends TextureSheetParticle {
super.tick();
}
public record Provider(SpriteSet spriteSet) implements ParticleProvider<ShriekParticleOptions> {
public record Provider(SpriteSet spriteSet)
implements ParticleProvider<ShriekParticleOptions> {
@Override
public Particle createParticle(ShriekParticleOptions options, ClientLevel level, double x, double y, double z, double xMotion, double yMotion, double zMotion) {
public Particle createParticle(
ShriekParticleOptions options,
ClientLevel level,
double x,
double y,
double z,
double xMotion,
double yMotion,
double zMotion
) {
ShriekParticle particle = new ShriekParticle(level, x, y, z, options.delay());
particle.pickSprite(this.spriteSet);
particle.setAlpha(1.0F);

View file

@ -1,5 +1,7 @@
package com.cursedcauldron.wildbackport.client.particle;
import java.util.Locale;
import com.cursedcauldron.wildbackport.client.registry.WBParticleTypes;
import com.mojang.brigadier.StringReader;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
@ -10,27 +12,33 @@ import net.minecraft.core.particles.ParticleOptions;
import net.minecraft.core.particles.ParticleType;
import net.minecraft.network.FriendlyByteBuf;
import java.util.Locale;
public record ShriekParticleOptions(int delay) implements ParticleOptions {
public static final Codec<ShriekParticleOptions> CODEC = RecordCodecBuilder.create(instance -> {
return instance.group(Codec.INT.fieldOf("delay").forGetter(options -> {
return options.delay;
})).apply(instance, ShriekParticleOptions::new);
});
public static final Codec<ShriekParticleOptions> CODEC
= RecordCodecBuilder.create(instance -> {
return instance
.group(Codec.INT.fieldOf("delay").forGetter(options -> {
return options.delay;
}))
.apply(instance, ShriekParticleOptions::new);
});
public static final ParticleOptions.Deserializer<ShriekParticleOptions> DESERIALIZER = new ParticleOptions.Deserializer<>() {
@Override
public ShriekParticleOptions fromCommand(ParticleType<ShriekParticleOptions> type, StringReader reader) throws CommandSyntaxException {
reader.expect(' ');
return new ShriekParticleOptions(reader.readInt());
}
public static final ParticleOptions.Deserializer<ShriekParticleOptions> DESERIALIZER
= new ParticleOptions.Deserializer<>() {
@Override
public ShriekParticleOptions fromCommand(
ParticleType<ShriekParticleOptions> type, StringReader reader
) throws CommandSyntaxException {
reader.expect(' ');
return new ShriekParticleOptions(reader.readInt());
}
@Override
public ShriekParticleOptions fromNetwork(ParticleType<ShriekParticleOptions> type, FriendlyByteBuf buf) {
return new ShriekParticleOptions(buf.readVarInt());
}
};
@Override
public ShriekParticleOptions fromNetwork(
ParticleType<ShriekParticleOptions> type, FriendlyByteBuf buf
) {
return new ShriekParticleOptions(buf.readVarInt());
}
};
@Override
public void writeToNetwork(FriendlyByteBuf buf) {
@ -39,7 +47,9 @@ public record ShriekParticleOptions(int delay) implements ParticleOptions {
@Override
public String writeToString() {
return String.format(Locale.ROOT, "%s %d", Registry.PARTICLE_TYPE.getId(this.getType()), this.delay);
return String.format(
Locale.ROOT, "%s %d", Registry.PARTICLE_TYPE.getId(this.getType()), this.delay
);
}
@Override

View file

@ -8,16 +8,28 @@ import net.minecraft.client.particle.SpriteSet;
import net.minecraft.core.particles.SimpleParticleType;
public class SonicBoomParticle extends HugeExplosionParticle {
public SonicBoomParticle(ClientLevel level, double x, double y, double z, double speed, SpriteSet sprites) {
public SonicBoomParticle(
ClientLevel level, double x, double y, double z, double speed, SpriteSet sprites
) {
super(level, x, y, z, speed, sprites);
this.lifetime = 16;
this.quadSize = 1.5F;
this.setSpriteFromAge(sprites);
}
public record Provider(SpriteSet sprites) implements ParticleProvider<SimpleParticleType> {
public record Provider(SpriteSet sprites)
implements ParticleProvider<SimpleParticleType> {
@Override
public Particle createParticle(SimpleParticleType particle, ClientLevel level, double x, double y, double z, double xMotion, double yMotion, double zMotion) {
public Particle createParticle(
SimpleParticleType particle,
ClientLevel level,
double x,
double y,
double z,
double xMotion,
double yMotion,
double zMotion
) {
return new SonicBoomParticle(level, x, y, z, xMotion, this.sprites);
}
}

View file

@ -11,9 +11,16 @@ import net.minecraft.resources.ResourceLocation;
//<>
public class WBCriteriaTriggers {
public static final KilledTrigger KILL_MOB_NEAR_SCULK_CATALYST = create(new KilledTrigger(new ResourceLocation("minecraft", "kill_mob_near_sculk_catalyst")));
// public static final ItemUsedOnBlockTrigger ALLAY_DROP_ITEM_ON_BLOCK = create(new ItemUsedOnBlockTrigger(new ResourceLocation(WildBackport.MOD_ID, "kill_mob_near_sculk_catalyst")));
public static final LocationTrigger AVOID_VIBRATION = create(new LocationTrigger(new ResourceLocation("minecraft", "avoid_vibration")));
public static final KilledTrigger KILL_MOB_NEAR_SCULK_CATALYST
= create(new KilledTrigger(
new ResourceLocation("minecraft", "kill_mob_near_sculk_catalyst")
));
// public static final ItemUsedOnBlockTrigger ALLAY_DROP_ITEM_ON_BLOCK = create(new
// ItemUsedOnBlockTrigger(new ResourceLocation(WildBackport.MOD_ID,
// "kill_mob_near_sculk_catalyst")));
public static final LocationTrigger AVOID_VIBRATION
= create(new LocationTrigger(new ResourceLocation("minecraft", "avoid_vibration"))
);
public static <T extends CriterionTrigger<?>> T create(T type) {
return CriteriaTriggersAccessor.callRegister(type);

View file

@ -1,5 +1,8 @@
package com.cursedcauldron.wildbackport.client.registry;
import java.util.function.Function;
import java.util.function.Supplier;
import com.cursedcauldron.wildbackport.WildBackport;
import com.cursedcauldron.wildbackport.client.particle.SculkChargeParticleOptions;
import com.cursedcauldron.wildbackport.client.particle.ShriekParticleOptions;
@ -11,29 +14,54 @@ import net.minecraft.core.particles.ParticleOptions;
import net.minecraft.core.particles.ParticleType;
import net.minecraft.core.particles.SimpleParticleType;
import java.util.function.Function;
import java.util.function.Supplier;
//<>
public class WBParticleTypes {
public static final CoreRegistry<ParticleType<?>> PARTICLES = CoreRegistry.create(Registry.PARTICLE_TYPE, "minecraft");
public static final CoreRegistry<ParticleType<?>> PARTICLES
= CoreRegistry.create(Registry.PARTICLE_TYPE, "minecraft");
public static final Supplier<SimpleParticleType> SCULK_SOUL = create("sculk_soul", false);
public static final Supplier<ParticleType<SculkChargeParticleOptions>> SCULK_CHARGE = create("sculk_charge", SculkChargeParticleOptions.DESERIALIZER, type -> SculkChargeParticleOptions.CODEC, true);
public static final Supplier<SimpleParticleType> SCULK_CHARGE_POP = create("sculk_charge_pop", true);
public static final Supplier<ParticleType<ShriekParticleOptions>> SHRIEK = create("shriek", ShriekParticleOptions.DESERIALIZER, type -> ShriekParticleOptions.CODEC, true);
public static final Supplier<SimpleParticleType> SONIC_BOOM = create("sonic_boom", true);
public static final Supplier<SimpleParticleType> SCULK_SOUL
= create("sculk_soul", false);
public static final Supplier<ParticleType<SculkChargeParticleOptions>> SCULK_CHARGE
= create(
"sculk_charge",
SculkChargeParticleOptions.DESERIALIZER,
type
-> SculkChargeParticleOptions.CODEC,
true
);
public static final Supplier<SimpleParticleType> SCULK_CHARGE_POP
= create("sculk_charge_pop", true);
public static final Supplier<ParticleType<ShriekParticleOptions>> SHRIEK = create(
"shriek",
ShriekParticleOptions.DESERIALIZER,
type
-> ShriekParticleOptions.CODEC,
true
);
public static final Supplier<SimpleParticleType> SONIC_BOOM
= create("sonic_boom", true);
private static Supplier<SimpleParticleType> create(String key, boolean alwaysShow) {
return PARTICLES.register(key, () -> SimpleParticleTypeAccessor.createSimpleParticleType(alwaysShow));
return PARTICLES.register(
key, () -> SimpleParticleTypeAccessor.createSimpleParticleType(alwaysShow)
);
}
private static <T extends ParticleOptions> Supplier<ParticleType<T>> create(String key, ParticleOptions.Deserializer<T> deserializer, Function<ParticleType<T>, Codec<T>> function, boolean alwaysShow) {
return PARTICLES.register(key, () -> new ParticleType<>(alwaysShow, deserializer) {
@Override public Codec<T> codec() {
return function.apply(this);
private static <T extends ParticleOptions> Supplier<ParticleType<T>> create(
String key,
ParticleOptions.Deserializer<T> deserializer,
Function<ParticleType<T>, Codec<T>> function,
boolean alwaysShow
) {
return PARTICLES.register(
key,
() -> new ParticleType<>(alwaysShow, deserializer) {
@Override
public Codec<T> codec() {
return function.apply(this);
}
}
});
);
}
}

View file

@ -1,5 +1,7 @@
package com.cursedcauldron.wildbackport.client.registry;
import java.util.stream.IntStream;
import com.cursedcauldron.wildbackport.WildBackport;
import com.cursedcauldron.wildbackport.core.api.CoreRegistry;
import com.google.common.collect.ImmutableList;
@ -7,128 +9,181 @@ import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.sounds.SoundEvent;
import java.util.stream.IntStream;
//<>
public class WBSoundEvents {
public static final CoreRegistry<SoundEvent> SOUNDS = CoreRegistry.create(Registry.SOUND_EVENT, "minecraft");
public static final CoreRegistry<SoundEvent> SOUNDS
= CoreRegistry.create(Registry.SOUND_EVENT, "minecraft");
// Blocks
public static final SoundEvent BLOCK_SCULK_VEIN_BREAK = create("block.sculk_vein.break");
public static final SoundEvent BLOCK_SCULK_VEIN_FALL = create("block.sculk_vein.fall");
public static final SoundEvent BLOCK_SCULK_VEIN_HIT = create("block.sculk_vein.hit");
public static final SoundEvent BLOCK_SCULK_VEIN_PLACE = create("block.sculk_vein.place");
public static final SoundEvent BLOCK_SCULK_VEIN_STEP = create("block.sculk_vein.step");
public static final SoundEvent BLOCK_SCULK_CATALYST_BLOOM = create("block.sculk_catalyst.bloom");
public static final SoundEvent BLOCK_SCULK_CATALYST_BREAK = create("block.sculk_catalyst.break");
public static final SoundEvent BLOCK_SCULK_CATALYST_FALL = create("block.sculk_catalyst.fall");
public static final SoundEvent BLOCK_SCULK_CATALYST_HIT = create("block.sculk_catalyst.hit");
public static final SoundEvent BLOCK_SCULK_CATALYST_PLACE = create("block.sculk_catalyst.place");
public static final SoundEvent BLOCK_SCULK_CATALYST_STEP = create("block.sculk_catalyst.step");
public static final SoundEvent BLOCK_SCULK_SPREAD = create("block.sculk.spread");
public static final SoundEvent BLOCK_SCULK_CHARGE = create("block.sculk.charge");
public static final SoundEvent BLOCK_SCULK_BREAK = create("block.sculk.break");
public static final SoundEvent BLOCK_SCULK_FALL = create("block.sculk.fall");
public static final SoundEvent BLOCK_SCULK_HIT = create("block.sculk.hit");
public static final SoundEvent BLOCK_SCULK_PLACE = create("block.sculk.place");
public static final SoundEvent BLOCK_SCULK_STEP = create("block.sculk.step");
public static final SoundEvent BLOCK_SCULK_SHRIEKER_BREAK = create("block.sculk_shrieker.break");
public static final SoundEvent BLOCK_SCULK_SHRIEKER_FALL = create("block.sculk_shrieker.fall");
public static final SoundEvent BLOCK_SCULK_SHRIEKER_HIT = create("block.sculk_shrieker.hit");
public static final SoundEvent BLOCK_SCULK_SHRIEKER_PLACE = create("block.sculk_shrieker.place");
public static final SoundEvent BLOCK_SCULK_SHRIEKER_STEP = create("block.sculk_shrieker.step");
public static final SoundEvent BLOCK_SCULK_SHRIEKER_SHRIEK = create("block.sculk_shrieker.shriek");
public static final SoundEvent BLOCK_FROGLIGHT_BREAK = create("block.froglight.break");
public static final SoundEvent BLOCK_FROGLIGHT_FALL = create("block.froglight.fall");
public static final SoundEvent BLOCK_FROGLIGHT_HIT = create("block.froglight.hit");
public static final SoundEvent BLOCK_FROGLIGHT_PLACE = create("block.froglight.place");
public static final SoundEvent BLOCK_FROGLIGHT_STEP = create("block.froglight.step");
public static final SoundEvent BLOCK_FROGSPAWN_BREAK = create("block.frogspawn.break");
public static final SoundEvent BLOCK_FROGSPAWN_FALL = create("block.frogspawn.fall");
public static final SoundEvent BLOCK_FROGSPAWN_HATCH = create("block.frogspawn.hatch");
public static final SoundEvent BLOCK_FROGSPAWN_HIT = create("block.frogspawn.hit");
public static final SoundEvent BLOCK_FROGSPAWN_PLACE = create("block.frogspawn.place");
public static final SoundEvent BLOCK_FROGSPAWN_STEP = create("block.frogspawn.step");
public static final SoundEvent BLOCK_MANGROVE_ROOTS_BREAK = create("block.mangrove_roots.break");
public static final SoundEvent BLOCK_MANGROVE_ROOTS_FALL = create("block.mangrove_roots.fall");
public static final SoundEvent BLOCK_MANGROVE_ROOTS_HIT = create("block.mangrove_roots.hit");
public static final SoundEvent BLOCK_MANGROVE_ROOTS_PLACE = create("block.mangrove_roots.place");
public static final SoundEvent BLOCK_MANGROVE_ROOTS_STEP = create("block.mangrove_roots.step");
public static final SoundEvent BLOCK_MUD_BREAK = create("block.mud.break");
public static final SoundEvent BLOCK_MUD_FALL = create("block.mud.fall");
public static final SoundEvent BLOCK_MUD_HIT = create("block.mud.hit");
public static final SoundEvent BLOCK_MUD_PLACE = create("block.mud.place");
public static final SoundEvent BLOCK_MUD_STEP = create("block.mud.step");
public static final SoundEvent BLOCK_MUD_BRICKS_BREAK = create("block.mud_bricks.break");
public static final SoundEvent BLOCK_MUD_BRICKS_FALL = create("block.mud_bricks.fall");
public static final SoundEvent BLOCK_MUD_BRICKS_HIT = create("block.mud_bricks.hit");
public static final SoundEvent BLOCK_MUD_BRICKS_PLACE = create("block.mud_bricks.place");
public static final SoundEvent BLOCK_MUD_BRICKS_STEP = create("block.mud_bricks.step");
public static final SoundEvent BLOCK_MUDDY_MANGROVE_ROOTS_BREAK = create("block.muddy_mangrove_roots.break");
public static final SoundEvent BLOCK_MUDDY_MANGROVE_ROOTS_FALL = create("block.muddy_mangrove_roots.fall");
public static final SoundEvent BLOCK_MUDDY_MANGROVE_ROOTS_HIT = create("block.muddy_mangrove_roots.hit");
public static final SoundEvent BLOCK_MUDDY_MANGROVE_ROOTS_PLACE = create("block.muddy_mangrove_roots.place");
public static final SoundEvent BLOCK_MUDDY_MANGROVE_ROOTS_STEP = create("block.muddy_mangrove_roots.step");
public static final SoundEvent BLOCK_PACKED_MUD_BREAK = create("block.packed_mud.break");
public static final SoundEvent BLOCK_PACKED_MUD_FALL = create("block.packed_mud.fall");
public static final SoundEvent BLOCK_PACKED_MUD_HIT = create("block.packed_mud.hit");
public static final SoundEvent BLOCK_PACKED_MUD_PLACE = create("block.packed_mud.place");
public static final SoundEvent BLOCK_PACKED_MUD_STEP = create("block.packed_mud.step");
public static final SoundEvent BLOCK_SCULK_VEIN_BREAK
= create("block.sculk_vein.break");
public static final SoundEvent BLOCK_SCULK_VEIN_FALL
= create("block.sculk_vein.fall");
public static final SoundEvent BLOCK_SCULK_VEIN_HIT = create("block.sculk_vein.hit");
public static final SoundEvent BLOCK_SCULK_VEIN_PLACE
= create("block.sculk_vein.place");
public static final SoundEvent BLOCK_SCULK_VEIN_STEP
= create("block.sculk_vein.step");
public static final SoundEvent BLOCK_SCULK_CATALYST_BLOOM
= create("block.sculk_catalyst.bloom");
public static final SoundEvent BLOCK_SCULK_CATALYST_BREAK
= create("block.sculk_catalyst.break");
public static final SoundEvent BLOCK_SCULK_CATALYST_FALL
= create("block.sculk_catalyst.fall");
public static final SoundEvent BLOCK_SCULK_CATALYST_HIT
= create("block.sculk_catalyst.hit");
public static final SoundEvent BLOCK_SCULK_CATALYST_PLACE
= create("block.sculk_catalyst.place");
public static final SoundEvent BLOCK_SCULK_CATALYST_STEP
= create("block.sculk_catalyst.step");
public static final SoundEvent BLOCK_SCULK_SPREAD = create("block.sculk.spread");
public static final SoundEvent BLOCK_SCULK_CHARGE = create("block.sculk.charge");
public static final SoundEvent BLOCK_SCULK_BREAK = create("block.sculk.break");
public static final SoundEvent BLOCK_SCULK_FALL = create("block.sculk.fall");
public static final SoundEvent BLOCK_SCULK_HIT = create("block.sculk.hit");
public static final SoundEvent BLOCK_SCULK_PLACE = create("block.sculk.place");
public static final SoundEvent BLOCK_SCULK_STEP = create("block.sculk.step");
public static final SoundEvent BLOCK_SCULK_SHRIEKER_BREAK
= create("block.sculk_shrieker.break");
public static final SoundEvent BLOCK_SCULK_SHRIEKER_FALL
= create("block.sculk_shrieker.fall");
public static final SoundEvent BLOCK_SCULK_SHRIEKER_HIT
= create("block.sculk_shrieker.hit");
public static final SoundEvent BLOCK_SCULK_SHRIEKER_PLACE
= create("block.sculk_shrieker.place");
public static final SoundEvent BLOCK_SCULK_SHRIEKER_STEP
= create("block.sculk_shrieker.step");
public static final SoundEvent BLOCK_SCULK_SHRIEKER_SHRIEK
= create("block.sculk_shrieker.shriek");
public static final SoundEvent BLOCK_FROGLIGHT_BREAK
= create("block.froglight.break");
public static final SoundEvent BLOCK_FROGLIGHT_FALL = create("block.froglight.fall");
public static final SoundEvent BLOCK_FROGLIGHT_HIT = create("block.froglight.hit");
public static final SoundEvent BLOCK_FROGLIGHT_PLACE
= create("block.froglight.place");
public static final SoundEvent BLOCK_FROGLIGHT_STEP = create("block.froglight.step");
public static final SoundEvent BLOCK_FROGSPAWN_BREAK
= create("block.frogspawn.break");
public static final SoundEvent BLOCK_FROGSPAWN_FALL = create("block.frogspawn.fall");
public static final SoundEvent BLOCK_FROGSPAWN_HATCH
= create("block.frogspawn.hatch");
public static final SoundEvent BLOCK_FROGSPAWN_HIT = create("block.frogspawn.hit");
public static final SoundEvent BLOCK_FROGSPAWN_PLACE
= create("block.frogspawn.place");
public static final SoundEvent BLOCK_FROGSPAWN_STEP = create("block.frogspawn.step");
public static final SoundEvent BLOCK_MANGROVE_ROOTS_BREAK
= create("block.mangrove_roots.break");
public static final SoundEvent BLOCK_MANGROVE_ROOTS_FALL
= create("block.mangrove_roots.fall");
public static final SoundEvent BLOCK_MANGROVE_ROOTS_HIT
= create("block.mangrove_roots.hit");
public static final SoundEvent BLOCK_MANGROVE_ROOTS_PLACE
= create("block.mangrove_roots.place");
public static final SoundEvent BLOCK_MANGROVE_ROOTS_STEP
= create("block.mangrove_roots.step");
public static final SoundEvent BLOCK_MUD_BREAK = create("block.mud.break");
public static final SoundEvent BLOCK_MUD_FALL = create("block.mud.fall");
public static final SoundEvent BLOCK_MUD_HIT = create("block.mud.hit");
public static final SoundEvent BLOCK_MUD_PLACE = create("block.mud.place");
public static final SoundEvent BLOCK_MUD_STEP = create("block.mud.step");
public static final SoundEvent BLOCK_MUD_BRICKS_BREAK
= create("block.mud_bricks.break");
public static final SoundEvent BLOCK_MUD_BRICKS_FALL
= create("block.mud_bricks.fall");
public static final SoundEvent BLOCK_MUD_BRICKS_HIT = create("block.mud_bricks.hit");
public static final SoundEvent BLOCK_MUD_BRICKS_PLACE
= create("block.mud_bricks.place");
public static final SoundEvent BLOCK_MUD_BRICKS_STEP
= create("block.mud_bricks.step");
public static final SoundEvent BLOCK_MUDDY_MANGROVE_ROOTS_BREAK
= create("block.muddy_mangrove_roots.break");
public static final SoundEvent BLOCK_MUDDY_MANGROVE_ROOTS_FALL
= create("block.muddy_mangrove_roots.fall");
public static final SoundEvent BLOCK_MUDDY_MANGROVE_ROOTS_HIT
= create("block.muddy_mangrove_roots.hit");
public static final SoundEvent BLOCK_MUDDY_MANGROVE_ROOTS_PLACE
= create("block.muddy_mangrove_roots.place");
public static final SoundEvent BLOCK_MUDDY_MANGROVE_ROOTS_STEP
= create("block.muddy_mangrove_roots.step");
public static final SoundEvent BLOCK_PACKED_MUD_BREAK
= create("block.packed_mud.break");
public static final SoundEvent BLOCK_PACKED_MUD_FALL
= create("block.packed_mud.fall");
public static final SoundEvent BLOCK_PACKED_MUD_HIT = create("block.packed_mud.hit");
public static final SoundEvent BLOCK_PACKED_MUD_PLACE
= create("block.packed_mud.place");
public static final SoundEvent BLOCK_PACKED_MUD_STEP
= create("block.packed_mud.step");
// Items
public static final SoundEvent BUCKED_EMPTY_TADPOLE = create("item.bucket.empty_tadpole");
public static final SoundEvent BUCKED_FILL_TADPOLE = create("item.bucket.fill_tadpole");
public static final ImmutableList<SoundEvent> GOAT_HORN_SOUNDS = IntStream.range(0, 8).mapToObj(value -> {
return create("item.goat_horn.sound." + value);
}).collect(ImmutableList.toImmutableList());
public static final SoundEvent BUCKED_EMPTY_TADPOLE
= create("item.bucket.empty_tadpole");
public static final SoundEvent BUCKED_FILL_TADPOLE
= create("item.bucket.fill_tadpole");
public static final ImmutableList<SoundEvent> GOAT_HORN_SOUNDS
= IntStream.range(0, 8)
.mapToObj(value -> { return create("item.goat_horn.sound." + value); })
.collect(ImmutableList.toImmutableList());
// Entities
public static final SoundEvent ALLAY_AMBIENT_WITH_ITEM = create("entity.allay.ambient_with_item");
public static final SoundEvent ALLAY_AMBIENT_WITHOUT_ITEM = create("entity.allay.ambient_without_item");
public static final SoundEvent ALLAY_DEATH = create("entity.allay.death");
public static final SoundEvent ALLAY_HURT = create("entity.allay.hurt");
public static final SoundEvent ALLAY_ITEM_GIVEN = create("entity.allay.item_given");
public static final SoundEvent ALLAY_ITEM_TAKEN = create("entity.allay.item_taken");
public static final SoundEvent ALLAY_ITEM_THROW = create("entity.allay.item_thrown");
public static final SoundEvent FROG_AMBIENT = create("entity.frog.ambient");
public static final SoundEvent FROG_DEATH = create("entity.frog.death");
public static final SoundEvent FROG_EAT = create("entity.frog.eat");
public static final SoundEvent FROG_HURT = create("entity.frog.hurt");
public static final SoundEvent FROG_LAY_SPAWN = create("entity.frog.lay_spawn");
public static final SoundEvent FROG_LONG_JUMP = create("entity.frog.long_jump");
public static final SoundEvent FROG_STEP = create("entity.frog.step");
public static final SoundEvent FROG_TONGUE = create("entity.frog.tongue");
// public static final SoundEvent PARROT_IMITATE_WARDEN = create("entity.parrot.imitate_warden");
public static final SoundEvent TADPOLE_DEATH = create("entity.tadpole.death");
public static final SoundEvent TADPOLE_FLOP = create("entity.tadpole.flop");
public static final SoundEvent TADPOLE_GROW_UP = create("entity.tadpole.grow_up");
public static final SoundEvent TADPOLE_HURT = create("entity.tadpole.hurt");
public static final SoundEvent WARDEN_AMBIENT = create("entity.warden.ambient");
public static final SoundEvent WARDEN_LISTENING = create("entity.warden.listening");
public static final SoundEvent WARDEN_LISTENING_ANGRY = create("entity.warden.listening_angry");
public static final SoundEvent WARDEN_ANGRY = create("entity.warden.angry");
public static final SoundEvent WARDEN_HURT = create("entity.warden.hurt");
public static final SoundEvent WARDEN_DEATH = create("entity.warden.death");
public static final SoundEvent WARDEN_STEP = create("entity.warden.step");
public static final SoundEvent WARDEN_TENDRIL_CLICKS = create("entity.warden.tendril_clicks");
public static final SoundEvent WARDEN_HEARTBEAT = create("entity.warden.heartbeat");
public static final SoundEvent WARDEN_AGITATED = create("entity.warden.agitated");
public static final SoundEvent WARDEN_ATTACK_IMPACT = create("entity.warden.attack_impact");
public static final SoundEvent WARDEN_ROAR = create("entity.warden.roar");
public static final SoundEvent WARDEN_SNIFF = create("entity.warden.sniff");
public static final SoundEvent WARDEN_EMERGE = create("entity.warden.emerge");
public static final SoundEvent WARDEN_DIG = create("entity.warden.dig");
public static final SoundEvent WARDEN_NEARBY_CLOSEST = create("entity.warden.nearby_closest");
public static final SoundEvent WARDEN_NEARBY_CLOSER = create("entity.warden.nearby_closer");
public static final SoundEvent WARDEN_NEARBY_CLOSE = create("entity.warden.nearby_close");
public static final SoundEvent WARDEN_SONIC_BOOM = create("entity.warden.sonic_boom");
public static final SoundEvent WARDEN_SONIC_CHARGE = create("entity.warden.sonic_charge");
public static final SoundEvent ALLAY_AMBIENT_WITH_ITEM
= create("entity.allay.ambient_with_item");
public static final SoundEvent ALLAY_AMBIENT_WITHOUT_ITEM
= create("entity.allay.ambient_without_item");
public static final SoundEvent ALLAY_DEATH = create("entity.allay.death");
public static final SoundEvent ALLAY_HURT = create("entity.allay.hurt");
public static final SoundEvent ALLAY_ITEM_GIVEN = create("entity.allay.item_given");
public static final SoundEvent ALLAY_ITEM_TAKEN = create("entity.allay.item_taken");
public static final SoundEvent ALLAY_ITEM_THROW = create("entity.allay.item_thrown");
public static final SoundEvent FROG_AMBIENT = create("entity.frog.ambient");
public static final SoundEvent FROG_DEATH = create("entity.frog.death");
public static final SoundEvent FROG_EAT = create("entity.frog.eat");
public static final SoundEvent FROG_HURT = create("entity.frog.hurt");
public static final SoundEvent FROG_LAY_SPAWN = create("entity.frog.lay_spawn");
public static final SoundEvent FROG_LONG_JUMP = create("entity.frog.long_jump");
public static final SoundEvent FROG_STEP = create("entity.frog.step");
public static final SoundEvent FROG_TONGUE = create("entity.frog.tongue");
// public static final SoundEvent PARROT_IMITATE_WARDEN =
// create("entity.parrot.imitate_warden");
public static final SoundEvent TADPOLE_DEATH = create("entity.tadpole.death");
public static final SoundEvent TADPOLE_FLOP = create("entity.tadpole.flop");
public static final SoundEvent TADPOLE_GROW_UP = create("entity.tadpole.grow_up");
public static final SoundEvent TADPOLE_HURT = create("entity.tadpole.hurt");
public static final SoundEvent WARDEN_AMBIENT = create("entity.warden.ambient");
public static final SoundEvent WARDEN_LISTENING = create("entity.warden.listening");
public static final SoundEvent WARDEN_LISTENING_ANGRY
= create("entity.warden.listening_angry");
public static final SoundEvent WARDEN_ANGRY = create("entity.warden.angry");
public static final SoundEvent WARDEN_HURT = create("entity.warden.hurt");
public static final SoundEvent WARDEN_DEATH = create("entity.warden.death");
public static final SoundEvent WARDEN_STEP = create("entity.warden.step");
public static final SoundEvent WARDEN_TENDRIL_CLICKS
= create("entity.warden.tendril_clicks");
public static final SoundEvent WARDEN_HEARTBEAT = create("entity.warden.heartbeat");
public static final SoundEvent WARDEN_AGITATED = create("entity.warden.agitated");
public static final SoundEvent WARDEN_ATTACK_IMPACT
= create("entity.warden.attack_impact");
public static final SoundEvent WARDEN_ROAR = create("entity.warden.roar");
public static final SoundEvent WARDEN_SNIFF = create("entity.warden.sniff");
public static final SoundEvent WARDEN_EMERGE = create("entity.warden.emerge");
public static final SoundEvent WARDEN_DIG = create("entity.warden.dig");
public static final SoundEvent WARDEN_NEARBY_CLOSEST
= create("entity.warden.nearby_closest");
public static final SoundEvent WARDEN_NEARBY_CLOSER
= create("entity.warden.nearby_closer");
public static final SoundEvent WARDEN_NEARBY_CLOSE
= create("entity.warden.nearby_close");
public static final SoundEvent WARDEN_SONIC_BOOM = create("entity.warden.sonic_boom");
public static final SoundEvent WARDEN_SONIC_CHARGE
= create("entity.warden.sonic_charge");
// Music
public static final SoundEvent MUSIC_DISC_5 = create("music_disc.5");
// public static final SoundEvent MUSIC_BIOME_DEEP_DARK = create("music.overworld.deep_dark");
public static final SoundEvent MUSIC_DISC_5 = create("music_disc.5");
// public static final SoundEvent MUSIC_BIOME_DEEP_DARK =
// create("music.overworld.deep_dark");
public static SoundEvent create(String key) {
SoundEvent sound = new SoundEvent(new ResourceLocation("minecraft", key));
SOUNDS.register(key, () -> sound);

View file

@ -7,19 +7,93 @@ import net.minecraft.world.level.block.SoundType;
//<>
public class WBSoundTypes {
public static final SoundType SCULK = create(WBSoundEvents.BLOCK_SCULK_BREAK, WBSoundEvents.BLOCK_SCULK_STEP, WBSoundEvents.BLOCK_SCULK_PLACE, WBSoundEvents.BLOCK_SCULK_HIT, WBSoundEvents.BLOCK_SCULK_FALL);
public static final SoundType SCULK_CATALYST = create(WBSoundEvents.BLOCK_SCULK_CATALYST_BREAK, WBSoundEvents.BLOCK_SCULK_CATALYST_STEP, WBSoundEvents.BLOCK_SCULK_CATALYST_PLACE, WBSoundEvents.BLOCK_SCULK_CATALYST_HIT, WBSoundEvents.BLOCK_SCULK_CATALYST_FALL);
public static final SoundType SCULK_VEIN = create(WBSoundEvents.BLOCK_SCULK_VEIN_BREAK, WBSoundEvents.BLOCK_SCULK_VEIN_STEP, WBSoundEvents.BLOCK_SCULK_VEIN_PLACE, WBSoundEvents.BLOCK_SCULK_VEIN_HIT, WBSoundEvents.BLOCK_SCULK_VEIN_FALL);
public static final SoundType SCULK_SHRIEKER = create(WBSoundEvents.BLOCK_SCULK_SHRIEKER_BREAK, WBSoundEvents.BLOCK_SCULK_SHRIEKER_STEP, WBSoundEvents.BLOCK_SCULK_SHRIEKER_PLACE, WBSoundEvents.BLOCK_SCULK_SHRIEKER_HIT, WBSoundEvents.BLOCK_SCULK_SHRIEKER_FALL);
public static final SoundType FROGLIGHT = create(WBSoundEvents.BLOCK_FROGLIGHT_BREAK, WBSoundEvents.BLOCK_FROGLIGHT_STEP, WBSoundEvents.BLOCK_FROGLIGHT_PLACE, WBSoundEvents.BLOCK_FROGLIGHT_HIT, WBSoundEvents.BLOCK_FROGLIGHT_FALL);
public static final SoundType FROGSPAWN = create(WBSoundEvents.BLOCK_FROGSPAWN_BREAK, WBSoundEvents.BLOCK_FROGSPAWN_STEP, WBSoundEvents.BLOCK_FROGSPAWN_PLACE, WBSoundEvents.BLOCK_FROGSPAWN_HIT, WBSoundEvents.BLOCK_FROGSPAWN_FALL);
public static final SoundType MANGROVE_ROOTS = create(WBSoundEvents.BLOCK_MANGROVE_ROOTS_BREAK, WBSoundEvents.BLOCK_MANGROVE_ROOTS_STEP, WBSoundEvents.BLOCK_MANGROVE_ROOTS_PLACE, WBSoundEvents.BLOCK_MANGROVE_ROOTS_HIT, WBSoundEvents.BLOCK_MANGROVE_ROOTS_FALL);
public static final SoundType MUD = create(WBSoundEvents.BLOCK_MUD_BREAK, WBSoundEvents.BLOCK_MUD_STEP, WBSoundEvents.BLOCK_MUD_PLACE, WBSoundEvents.BLOCK_MUD_HIT, WBSoundEvents.BLOCK_MUD_FALL);
public static final SoundType MUD_BRICKS = create(WBSoundEvents.BLOCK_MUD_BRICKS_BREAK, WBSoundEvents.BLOCK_MUD_BRICKS_STEP, WBSoundEvents.BLOCK_MUD_BRICKS_PLACE, WBSoundEvents.BLOCK_MUD_BRICKS_HIT, WBSoundEvents.BLOCK_MUD_BRICKS_FALL);
public static final SoundType MUDDY_MANGROVE_ROOTS = create(WBSoundEvents.BLOCK_MUDDY_MANGROVE_ROOTS_BREAK, WBSoundEvents.BLOCK_MUDDY_MANGROVE_ROOTS_STEP, WBSoundEvents.BLOCK_MUDDY_MANGROVE_ROOTS_PLACE, WBSoundEvents.BLOCK_MUDDY_MANGROVE_ROOTS_HIT, WBSoundEvents.BLOCK_MUDDY_MANGROVE_ROOTS_FALL);
public static final SoundType PACKED_MUD = create(WBSoundEvents.BLOCK_PACKED_MUD_BREAK, WBSoundEvents.BLOCK_PACKED_MUD_STEP, WBSoundEvents.BLOCK_PACKED_MUD_PLACE, WBSoundEvents.BLOCK_PACKED_MUD_HIT, WBSoundEvents.BLOCK_PACKED_MUD_FALL);
public static final SoundType SCULK = create(
WBSoundEvents.BLOCK_SCULK_BREAK,
WBSoundEvents.BLOCK_SCULK_STEP,
WBSoundEvents.BLOCK_SCULK_PLACE,
WBSoundEvents.BLOCK_SCULK_HIT,
WBSoundEvents.BLOCK_SCULK_FALL
);
public static final SoundType SCULK_CATALYST = create(
WBSoundEvents.BLOCK_SCULK_CATALYST_BREAK,
WBSoundEvents.BLOCK_SCULK_CATALYST_STEP,
WBSoundEvents.BLOCK_SCULK_CATALYST_PLACE,
WBSoundEvents.BLOCK_SCULK_CATALYST_HIT,
WBSoundEvents.BLOCK_SCULK_CATALYST_FALL
);
public static final SoundType SCULK_VEIN = create(
WBSoundEvents.BLOCK_SCULK_VEIN_BREAK,
WBSoundEvents.BLOCK_SCULK_VEIN_STEP,
WBSoundEvents.BLOCK_SCULK_VEIN_PLACE,
WBSoundEvents.BLOCK_SCULK_VEIN_HIT,
WBSoundEvents.BLOCK_SCULK_VEIN_FALL
);
public static final SoundType SCULK_SHRIEKER = create(
WBSoundEvents.BLOCK_SCULK_SHRIEKER_BREAK,
WBSoundEvents.BLOCK_SCULK_SHRIEKER_STEP,
WBSoundEvents.BLOCK_SCULK_SHRIEKER_PLACE,
WBSoundEvents.BLOCK_SCULK_SHRIEKER_HIT,
WBSoundEvents.BLOCK_SCULK_SHRIEKER_FALL
);
public static final SoundType FROGLIGHT = create(
WBSoundEvents.BLOCK_FROGLIGHT_BREAK,
WBSoundEvents.BLOCK_FROGLIGHT_STEP,
WBSoundEvents.BLOCK_FROGLIGHT_PLACE,
WBSoundEvents.BLOCK_FROGLIGHT_HIT,
WBSoundEvents.BLOCK_FROGLIGHT_FALL
);
public static final SoundType FROGSPAWN = create(
WBSoundEvents.BLOCK_FROGSPAWN_BREAK,
WBSoundEvents.BLOCK_FROGSPAWN_STEP,
WBSoundEvents.BLOCK_FROGSPAWN_PLACE,
WBSoundEvents.BLOCK_FROGSPAWN_HIT,
WBSoundEvents.BLOCK_FROGSPAWN_FALL
);
public static final SoundType MANGROVE_ROOTS = create(
WBSoundEvents.BLOCK_MANGROVE_ROOTS_BREAK,
WBSoundEvents.BLOCK_MANGROVE_ROOTS_STEP,
WBSoundEvents.BLOCK_MANGROVE_ROOTS_PLACE,
WBSoundEvents.BLOCK_MANGROVE_ROOTS_HIT,
WBSoundEvents.BLOCK_MANGROVE_ROOTS_FALL
);
public static final SoundType MUD = create(
WBSoundEvents.BLOCK_MUD_BREAK,
WBSoundEvents.BLOCK_MUD_STEP,
WBSoundEvents.BLOCK_MUD_PLACE,
WBSoundEvents.BLOCK_MUD_HIT,
WBSoundEvents.BLOCK_MUD_FALL
);
public static final SoundType MUD_BRICKS = create(
WBSoundEvents.BLOCK_MUD_BRICKS_BREAK,
WBSoundEvents.BLOCK_MUD_BRICKS_STEP,
WBSoundEvents.BLOCK_MUD_BRICKS_PLACE,
WBSoundEvents.BLOCK_MUD_BRICKS_HIT,
WBSoundEvents.BLOCK_MUD_BRICKS_FALL
);
public static final SoundType MUDDY_MANGROVE_ROOTS = create(
WBSoundEvents.BLOCK_MUDDY_MANGROVE_ROOTS_BREAK,
WBSoundEvents.BLOCK_MUDDY_MANGROVE_ROOTS_STEP,
WBSoundEvents.BLOCK_MUDDY_MANGROVE_ROOTS_PLACE,
WBSoundEvents.BLOCK_MUDDY_MANGROVE_ROOTS_HIT,
WBSoundEvents.BLOCK_MUDDY_MANGROVE_ROOTS_FALL
);
public static final SoundType PACKED_MUD = create(
WBSoundEvents.BLOCK_PACKED_MUD_BREAK,
WBSoundEvents.BLOCK_PACKED_MUD_STEP,
WBSoundEvents.BLOCK_PACKED_MUD_PLACE,
WBSoundEvents.BLOCK_PACKED_MUD_HIT,
WBSoundEvents.BLOCK_PACKED_MUD_FALL
);
public static SoundType create(SoundEvent breakSnd, SoundEvent stepSnd, SoundEvent placeSnd, SoundEvent hitSnd, SoundEvent fallSnd) {
return new CoreSoundType(() -> breakSnd, () -> stepSnd, () -> placeSnd, () -> hitSnd, () -> fallSnd);
}
public static SoundType create(
SoundEvent breakSnd,
SoundEvent stepSnd,
SoundEvent placeSnd,
SoundEvent hitSnd,
SoundEvent fallSnd
) {
return new CoreSoundType(
() -> breakSnd, () -> stepSnd, () -> placeSnd, () -> hitSnd, () -> fallSnd
);
}
}

View file

@ -11,8 +11,10 @@ import net.minecraft.core.BlockPos;
import net.minecraft.resources.ResourceLocation;
public class AllayRenderer extends MobRenderer<Allay, AllayModel> {
public static final ModelLayerLocation MODEL_LAYER = new ModelLayerLocation(new ResourceLocation("minecraft", "allay"), "main");
private static final ResourceLocation TEXTURE = new ResourceLocation("minecraft", "textures/entity/allay/allay.png");
public static final ModelLayerLocation MODEL_LAYER
= new ModelLayerLocation(new ResourceLocation("minecraft", "allay"), "main");
private static final ResourceLocation TEXTURE
= new ResourceLocation("minecraft", "textures/entity/allay/allay.png");
public AllayRenderer(EntityRendererProvider.Context context) {
super(context, new AllayModel(context.bakeLayer(MODEL_LAYER)), 0.4F);

View file

@ -1,5 +1,8 @@
package com.cursedcauldron.wildbackport.client.render;
import java.util.Map;
import java.util.stream.Stream;
import com.cursedcauldron.wildbackport.WildBackport;
import com.cursedcauldron.wildbackport.client.render.model.ChestBoatModel;
import com.cursedcauldron.wildbackport.common.entities.MangroveBoat;
@ -21,9 +24,6 @@ import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.vehicle.Boat;
import java.util.Map;
import java.util.stream.Stream;
//<>
public class ChestBoatRenderer extends EntityRenderer<MangroveBoat> {
@ -32,47 +32,82 @@ public class ChestBoatRenderer extends EntityRenderer<MangroveBoat> {
public ChestBoatRenderer(EntityRendererProvider.Context context, boolean chest) {
super(context);
this.shadowRadius = 0.8F;
this.boatResources = Stream.of(Boat.Type.values()).collect(ImmutableMap.toImmutableMap(type -> type, type -> Pair.of(getTexture(type, chest), this.createModel(context, type, chest))));
this.boatResources
= Stream.of(Boat.Type.values())
.collect(ImmutableMap.toImmutableMap(
type
-> type,
type
-> Pair.of(
getTexture(type, chest), this.createModel(context, type, chest)
)
));
}
private ChestBoatModel createModel(EntityRendererProvider.Context context, Boat.Type type, boolean chest) {
ModelLayerLocation layer = chest ? ChestBoatModel.createChestBoat(type) : ModelLayers.createBoatModelName(type);
private ChestBoatModel
createModel(EntityRendererProvider.Context context, Boat.Type type, boolean chest) {
ModelLayerLocation layer = chest ? ChestBoatModel.createChestBoat(type)
: ModelLayers.createBoatModelName(type);
return new ChestBoatModel(context.bakeLayer(layer), chest);
}
private static ResourceLocation getTexture(Boat.Type type, boolean chested) {
if (chested) {
return new ResourceLocation("minecraft", "textures/entity/chest_boat/" + type.getName() + ".png");
return new ResourceLocation(
"minecraft", "textures/entity/chest_boat/" + type.getName() + ".png"
);
} else {
return new ResourceLocation("minecraft", "textures/entity/boat/" + type.getName() + ".png");
return new ResourceLocation(
"minecraft", "textures/entity/boat/" + type.getName() + ".png"
);
}
}
@Override
public void render(MangroveBoat boat, float yaw, float angle, PoseStack stack, MultiBufferSource buffer, int light) {
public void render(
MangroveBoat boat,
float yaw,
float angle,
PoseStack stack,
MultiBufferSource buffer,
int light
) {
stack.pushPose();
stack.translate(0.0D, 0.375D, 0.0D);
stack.mulPose(Vector3f.YP.rotationDegrees(180.0F - yaw));
float hurtTilt = (float)boat.getHurtTime() - angle;
float hurtTilt = (float) boat.getHurtTime() - angle;
float damageTilt = boat.getDamage() - angle;
if (damageTilt < 0.0F) damageTilt = 0.0F;
if (damageTilt < 0.0F)
damageTilt = 0.0F;
if (hurtTilt > 0.0F) stack.mulPose(Vector3f.XP.rotationDegrees(Mth.sin(hurtTilt) * hurtTilt * damageTilt / 10.0F * (float)boat.getHurtDir()));
if (hurtTilt > 0.0F)
stack.mulPose(Vector3f.XP.rotationDegrees(
Mth.sin(hurtTilt) * hurtTilt * damageTilt / 10.0F
* (float) boat.getHurtDir()
));
float bubbleTilt = boat.getBubbleAngle(angle);
if (!Mth.equal(bubbleTilt, 0.0F)) stack.mulPose(new Quaternion(new Vector3f(1.0F, 0.0F, 1.0F), boat.getBubbleAngle(angle), true));
if (!Mth.equal(bubbleTilt, 0.0F))
stack.mulPose(new Quaternion(
new Vector3f(1.0F, 0.0F, 1.0F), boat.getBubbleAngle(angle), true
));
Pair<ResourceLocation, ChestBoatModel> resource = this.boatResources.get(boat.getBoatType());
Pair<ResourceLocation, ChestBoatModel> resource
= this.boatResources.get(boat.getBoatType());
ResourceLocation location = resource.first;
ChestBoatModel model = resource.second;
stack.scale(-1.0F, -1.0F, 1.0F);
stack.mulPose(Vector3f.YP.rotationDegrees(90.0F));
model.setupAnim(boat, angle, 0.0F, -0.1F, 0.0F, 0.0F);
VertexConsumer render = buffer.getBuffer(model.renderType(location));
model.renderToBuffer(stack, render, light, OverlayTexture.NO_OVERLAY, 1.0F, 1.0F, 1.0F, 1.0F);
model.renderToBuffer(
stack, render, light, OverlayTexture.NO_OVERLAY, 1.0F, 1.0F, 1.0F, 1.0F
);
if (!boat.isUnderWater()) {
VertexConsumer waterRender = buffer.getBuffer(RenderType.waterMask());
model.waterPatch().render(stack, waterRender, light, OverlayTexture.NO_OVERLAY);
model.waterPatch().render(
stack, waterRender, light, OverlayTexture.NO_OVERLAY
);
}
stack.popPose();

View file

@ -1,5 +1,7 @@
package com.cursedcauldron.wildbackport.client.render;
import java.util.Map;
import com.cursedcauldron.wildbackport.WildBackport;
import com.cursedcauldron.wildbackport.client.render.model.FrogModel;
import com.cursedcauldron.wildbackport.common.entities.Frog;
@ -10,16 +12,21 @@ import net.minecraft.client.renderer.entity.EntityRendererProvider;
import net.minecraft.client.renderer.entity.MobRenderer;
import net.minecraft.resources.ResourceLocation;
import java.util.Map;
public class FrogRenderer extends MobRenderer<Frog, FrogModel<Frog>> {
public static final ModelLayerLocation MODEL_LAYER = new ModelLayerLocation(new ResourceLocation("frog"), "main");
public static final ModelLayerLocation MODEL_LAYER
= new ModelLayerLocation(new ResourceLocation("frog"), "main");
private static final Map<Frog.Variant, ResourceLocation> TEXTURES = Util.make(Maps.newHashMap(), hashMap -> {
for (Frog.Variant variant : Frog.Variant.values()) {
hashMap.put(variant, new ResourceLocation(String.format("textures/entity/frog/%s_frog.png", variant.getName())));
}
});
private static final Map<Frog.Variant, ResourceLocation> TEXTURES
= Util.make(Maps.newHashMap(), hashMap -> {
for (Frog.Variant variant : Frog.Variant.values()) {
hashMap.put(
variant,
new ResourceLocation(String.format(
"textures/entity/frog/%s_frog.png", variant.getName()
))
);
}
});
public FrogRenderer(EntityRendererProvider.Context context) {
super(context, new FrogModel<>(context.bakeLayer(MODEL_LAYER)), 0.3f);

View file

@ -9,9 +9,11 @@ import net.minecraft.client.renderer.entity.MobRenderer;
import net.minecraft.resources.ResourceLocation;
public class TadpoleRenderer extends MobRenderer<Tadpole, TadpoleModel<Tadpole>> {
public static final ModelLayerLocation MODEL_LAYER = new ModelLayerLocation(new ResourceLocation("tadpole"), "main");
public static final ModelLayerLocation MODEL_LAYER
= new ModelLayerLocation(new ResourceLocation("tadpole"), "main");
private static final ResourceLocation TEXTURE = new ResourceLocation("textures/entity/tadpole/tadpole.png");
private static final ResourceLocation TEXTURE
= new ResourceLocation("textures/entity/tadpole/tadpole.png");
public TadpoleRenderer(EntityRendererProvider.Context context) {
super(context, new TadpoleModel<>(context.bakeLayer(MODEL_LAYER)), 0.14F);

View file

@ -1,5 +1,8 @@
package com.cursedcauldron.wildbackport.client.render;
import java.util.List;
import java.util.function.BiFunction;
import com.cursedcauldron.wildbackport.client.render.model.Drawable;
import com.cursedcauldron.wildbackport.client.render.model.WardenModel;
import com.cursedcauldron.wildbackport.common.entities.Warden;
@ -22,23 +25,48 @@ import net.minecraft.client.renderer.entity.RenderLayerParent;
import net.minecraft.client.renderer.entity.layers.RenderLayer;
import net.minecraft.resources.ResourceLocation;
import java.util.List;
import java.util.function.BiFunction;
//<>
@Environment(EnvType.CLIENT)
public class WardenLayerRenderer<T extends Warden, M extends WardenModel<T>> extends RenderLayer<T, M> {
public static final BiFunction<ResourceLocation, Boolean, RenderType> ENTITY_TRANSLUCENT_EMISSIVE = Util.memoize((location, create) -> {
RenderType.CompositeState compositeState = RenderType.CompositeState.builder().setShaderState(RenderStateShardAccessor.getRENDERTYPE_EYES_SHADER()).setTextureState(new RenderStateShard.TextureStateShard(location, false, false)).setTransparencyState(RenderStateShardAccessor.getTRANSLUCENT_TRANSPARENCY()).setCullState(RenderStateShardAccessor.getNO_CULL()).setWriteMaskState(RenderStateShardAccessor.getCOLOR_WRITE()).setOverlayState(RenderStateShardAccessor.getOVERLAY()).createCompositeState(create);
return RenderTypeAccessor.callCreate("entity_translucent_emissive", DefaultVertexFormat.NEW_ENTITY, VertexFormat.Mode.QUADS, 256, true, true, compositeState);
});
public class WardenLayerRenderer<T extends Warden, M extends WardenModel<T>>
extends RenderLayer<T, M> {
public static final BiFunction<ResourceLocation, Boolean, RenderType>
ENTITY_TRANSLUCENT_EMISSIVE = Util.memoize((location, create) -> {
RenderType.CompositeState compositeState
= RenderType.CompositeState.builder()
.setShaderState(RenderStateShardAccessor.getRENDERTYPE_EYES_SHADER()
)
.setTextureState(
new RenderStateShard.TextureStateShard(location, false, false)
)
.setTransparencyState(
RenderStateShardAccessor.getTRANSLUCENT_TRANSPARENCY()
)
.setCullState(RenderStateShardAccessor.getNO_CULL())
.setWriteMaskState(RenderStateShardAccessor.getCOLOR_WRITE())
.setOverlayState(RenderStateShardAccessor.getOVERLAY())
.createCompositeState(create);
return RenderTypeAccessor.callCreate(
"entity_translucent_emissive",
DefaultVertexFormat.NEW_ENTITY,
VertexFormat.Mode.QUADS,
256,
true,
true,
compositeState
);
});
private final ResourceLocation texture;
private final AnimationAngleAdjuster<T> animationAngleAdjuster;
private final ModelPartVisibility<T, M> modelPartVisibility;
public WardenLayerRenderer(RenderLayerParent<T, M> ctx, ResourceLocation texture, AnimationAngleAdjuster<T> animationAngleAdjuster, ModelPartVisibility<T, M> modelPartVisibility) {
public WardenLayerRenderer(
RenderLayerParent<T, M> ctx,
ResourceLocation texture,
AnimationAngleAdjuster<T> animationAngleAdjuster,
ModelPartVisibility<T, M> modelPartVisibility
) {
super(ctx);
this.texture = texture;
this.animationAngleAdjuster = animationAngleAdjuster;
@ -46,23 +74,49 @@ public class WardenLayerRenderer<T extends Warden, M extends WardenModel<T>> ext
}
@Override
public void render(PoseStack stack, MultiBufferSource source, int light, T entity, float angle, float distance, float tickDelta, float animationProgress, float yaw, float pitch) {
public void render(
PoseStack stack,
MultiBufferSource source,
int light,
T entity,
float angle,
float distance,
float tickDelta,
float animationProgress,
float yaw,
float pitch
) {
if (!entity.isInvisible()) {
this.updateModelPartVisibility();
VertexConsumer consumer = source.getBuffer(ENTITY_TRANSLUCENT_EMISSIVE.apply(this.texture, true));
this.getParentModel().renderToBuffer(stack, consumer, light, LivingEntityRenderer.getOverlayCoords(entity, 0.0F), 1.0F, 1.0F, 1.0F, this.animationAngleAdjuster.apply(entity, tickDelta, animationProgress));
VertexConsumer consumer
= source.getBuffer(ENTITY_TRANSLUCENT_EMISSIVE.apply(this.texture, true));
this.getParentModel().renderToBuffer(
stack,
consumer,
light,
LivingEntityRenderer.getOverlayCoords(entity, 0.0F),
1.0F,
1.0F,
1.0F,
this.animationAngleAdjuster.apply(entity, tickDelta, animationProgress)
);
this.unhideAllModelParts();
}
}
private void updateModelPartVisibility() {
List<ModelPart> parts = this.modelPartVisibility.getPartsToDraw(this.getParentModel());
this.getParentModel().root().getAllParts().forEach(part -> Drawable.of(part).setSkipDraw(true));
List<ModelPart> parts
= this.modelPartVisibility.getPartsToDraw(this.getParentModel());
this.getParentModel().root().getAllParts().forEach(
part -> Drawable.of(part).setSkipDraw(true)
);
parts.forEach(part -> Drawable.of(part).setSkipDraw(false));
}
private void unhideAllModelParts() {
this.getParentModel().root().getAllParts().forEach(part -> Drawable.of(part).setSkipDraw(false));
this.getParentModel().root().getAllParts().forEach(
part -> Drawable.of(part).setSkipDraw(false)
);
}
public interface AnimationAngleAdjuster<T extends Warden> {

View file

@ -15,21 +15,59 @@ import net.minecraft.util.Mth;
@Environment(EnvType.CLIENT)
public class WardenRenderer extends MobRenderer<Warden, WardenModel<Warden>> {
public static final ModelLayerLocation MODEL_LAYER = new ModelLayerLocation(new ResourceLocation("warden"), "main");
public static final ModelLayerLocation MODEL_LAYER
= new ModelLayerLocation(new ResourceLocation("warden"), "main");
private static final ResourceLocation TEXTURE = new ResourceLocation("textures/entity/warden/warden.png");
private static final ResourceLocation BIOLUMINESCENT_LAYER_TEXTURE = new ResourceLocation("textures/entity/warden/warden_bioluminescent_layer.png");
private static final ResourceLocation HEART_TEXTURE = new ResourceLocation("textures/entity/warden/warden_heart.png");
private static final ResourceLocation PULSATING_SPOTS_1_TEXTURE = new ResourceLocation("textures/entity/warden/warden_pulsating_spots_1.png");
private static final ResourceLocation PULSATING_SPOTS_2_TEXTURE = new ResourceLocation("textures/entity/warden/warden_pulsating_spots_2.png");
private static final ResourceLocation TEXTURE
= new ResourceLocation("textures/entity/warden/warden.png");
private static final ResourceLocation BIOLUMINESCENT_LAYER_TEXTURE
= new ResourceLocation("textures/entity/warden/warden_bioluminescent_layer.png");
private static final ResourceLocation HEART_TEXTURE
= new ResourceLocation("textures/entity/warden/warden_heart.png");
private static final ResourceLocation PULSATING_SPOTS_1_TEXTURE
= new ResourceLocation("textures/entity/warden/warden_pulsating_spots_1.png");
private static final ResourceLocation PULSATING_SPOTS_2_TEXTURE
= new ResourceLocation("textures/entity/warden/warden_pulsating_spots_2.png");
public WardenRenderer(EntityRendererProvider.Context ctx) {
super(ctx, new WardenModel<>(ctx.bakeLayer(MODEL_LAYER)), 0.9F);
this.addLayer(new WardenLayerRenderer<>(this, BIOLUMINESCENT_LAYER_TEXTURE, (entity, tickDelta, animationProgress) -> 1.0F, WardenModel::getHeadAndLimbs));
this.addLayer(new WardenLayerRenderer<>(this, PULSATING_SPOTS_1_TEXTURE, (entity, tickDelta, animationProgress) -> Math.max(0.0F, Mth.cos(animationProgress * 0.045F) * 0.25F), WardenModel::getBodyHeadAndLimbs));
this.addLayer(new WardenLayerRenderer<>(this, PULSATING_SPOTS_2_TEXTURE, (entity, tickDelta, animationProgress) -> Math.max(0.0F, Mth.cos(animationProgress * 0.045F + (float)Math.PI) * 0.25F), WardenModel::getBodyHeadAndLimbs));
this.addLayer(new WardenLayerRenderer<>(this, TEXTURE, (entity, tickDelta, animationProgress) -> entity.getTendrilPitch(tickDelta), WardenModel::getTendrils));
this.addLayer(new WardenLayerRenderer<>(this, HEART_TEXTURE, (entity, tickDelta, animationProgress) -> entity.getHeartPitch(tickDelta), WardenModel::getBody));
this.addLayer(new WardenLayerRenderer<>(
this,
BIOLUMINESCENT_LAYER_TEXTURE,
(entity, tickDelta, animationProgress)
-> 1.0F,
WardenModel::getHeadAndLimbs
));
this.addLayer(new WardenLayerRenderer<>(
this,
PULSATING_SPOTS_1_TEXTURE,
(entity, tickDelta, animationProgress)
-> Math.max(0.0F, Mth.cos(animationProgress * 0.045F) * 0.25F),
WardenModel::getBodyHeadAndLimbs
));
this.addLayer(new WardenLayerRenderer<>(
this,
PULSATING_SPOTS_2_TEXTURE,
(entity, tickDelta, animationProgress)
-> Math.max(
0.0F, Mth.cos(animationProgress * 0.045F + (float) Math.PI) * 0.25F
),
WardenModel::getBodyHeadAndLimbs
));
this.addLayer(new WardenLayerRenderer<>(
this,
TEXTURE,
(entity, tickDelta, animationProgress)
-> entity.getTendrilPitch(tickDelta),
WardenModel::getTendrils
));
this.addLayer(new WardenLayerRenderer<>(
this,
HEART_TEXTURE,
(entity, tickDelta, animationProgress)
-> entity.getHeartPitch(tickDelta),
WardenModel::getBody
));
}
@Override

View file

@ -40,25 +40,72 @@ public class AllayModel extends HierarchicalModel<Allay> implements ArmedModel {
public static LayerDefinition createBodyLayer() {
MeshDefinition mesh = new MeshDefinition();
PartDefinition root = mesh.getRoot().addOrReplaceChild("root", CubeListBuilder.create(), PartPose.offset(0.0F, 23.5F, 0.0F));
root.addOrReplaceChild("head", CubeListBuilder.create().texOffs(0, 0).addBox(-2.5F, -5.0F, -2.5F, 5.0F, 5.0F, 5.0F, new CubeDeformation(0.0F)), PartPose.offset(0.0F, -3.99F, 0.0F));
PartDefinition body = root.addOrReplaceChild("body", CubeListBuilder.create().texOffs(0, 10).addBox(-1.5F, 0.0F, -1.0F, 3.0F, 4.0F, 2.0F, new CubeDeformation(0.0F)).texOffs(0, 16).addBox(-1.5F, 0.0F, -1.0F, 3.0F, 5.0F, 2.0F, new CubeDeformation(-0.2F)), PartPose.offset(0.0F, -4.0F, 0.0F));
body.addOrReplaceChild("right_arm", CubeListBuilder.create().texOffs(23, 0).addBox(-0.75F, -0.5F, -1.0F, 1.0F, 4.0F, 2.0F, new CubeDeformation(-0.01F)), PartPose.offset(-1.75F, 0.5F, 0.0F));
body.addOrReplaceChild("left_arm", CubeListBuilder.create().texOffs(23, 6).addBox(-0.25F, -0.5F, -1.0F, 1.0F, 4.0F, 2.0F, new CubeDeformation(-0.01F)), PartPose.offset(1.75F, 0.5F, 0.0F));
body.addOrReplaceChild("right_wing", CubeListBuilder.create().texOffs(16, 14).addBox(0.0F, 1.0F, 0.0F, 0.0F, 5.0F, 8.0F, new CubeDeformation(0.0F)), PartPose.offset(-0.5F, 0.0F, 0.65F));
body.addOrReplaceChild("left_wing", CubeListBuilder.create().texOffs(16, 14).addBox(0.0F, 1.0F, 0.0F, 0.0F, 5.0F, 8.0F, new CubeDeformation(0.0F)), PartPose.offset(0.5F, 0.0F, 0.65F));
PartDefinition root = mesh.getRoot().addOrReplaceChild(
"root", CubeListBuilder.create(), PartPose.offset(0.0F, 23.5F, 0.0F)
);
root.addOrReplaceChild(
"head",
CubeListBuilder.create().texOffs(0, 0).addBox(
-2.5F, -5.0F, -2.5F, 5.0F, 5.0F, 5.0F, new CubeDeformation(0.0F)
),
PartPose.offset(0.0F, -3.99F, 0.0F)
);
PartDefinition body = root.addOrReplaceChild(
"body",
CubeListBuilder.create()
.texOffs(0, 10)
.addBox(-1.5F, 0.0F, -1.0F, 3.0F, 4.0F, 2.0F, new CubeDeformation(0.0F))
.texOffs(0, 16)
.addBox(-1.5F, 0.0F, -1.0F, 3.0F, 5.0F, 2.0F, new CubeDeformation(-0.2F)),
PartPose.offset(0.0F, -4.0F, 0.0F)
);
body.addOrReplaceChild(
"right_arm",
CubeListBuilder.create().texOffs(23, 0).addBox(
-0.75F, -0.5F, -1.0F, 1.0F, 4.0F, 2.0F, new CubeDeformation(-0.01F)
),
PartPose.offset(-1.75F, 0.5F, 0.0F)
);
body.addOrReplaceChild(
"left_arm",
CubeListBuilder.create().texOffs(23, 6).addBox(
-0.25F, -0.5F, -1.0F, 1.0F, 4.0F, 2.0F, new CubeDeformation(-0.01F)
),
PartPose.offset(1.75F, 0.5F, 0.0F)
);
body.addOrReplaceChild(
"right_wing",
CubeListBuilder.create().texOffs(16, 14).addBox(
0.0F, 1.0F, 0.0F, 0.0F, 5.0F, 8.0F, new CubeDeformation(0.0F)
),
PartPose.offset(-0.5F, 0.0F, 0.65F)
);
body.addOrReplaceChild(
"left_wing",
CubeListBuilder.create().texOffs(16, 14).addBox(
0.0F, 1.0F, 0.0F, 0.0F, 5.0F, 8.0F, new CubeDeformation(0.0F)
),
PartPose.offset(0.5F, 0.0F, 0.65F)
);
return LayerDefinition.create(mesh, 32, 32);
}
@Override
public void setupAnim(Allay entity, float angle, float distance, float animationProgress, float yaw, float pitch) {
public void setupAnim(
Allay entity,
float angle,
float distance,
float animationProgress,
float yaw,
float pitch
) {
this.root().getAllParts().forEach(Animated::resetToDefault);
this.head.xRot = pitch * ((float)Math.PI / 180F);
this.head.yRot = yaw * ((float)Math.PI / 180F);
float f = animationProgress * 20.0F * ((float)Math.PI / 180F) + distance;
float f1 = Mth.cos(f) * (float)Math.PI * 0.15F;
float f2 = animationProgress - (float)entity.tickCount;
float f3 = animationProgress * 9.0F * ((float)Math.PI / 180F);
this.head.xRot = pitch * ((float) Math.PI / 180F);
this.head.yRot = yaw * ((float) Math.PI / 180F);
float f = animationProgress * 20.0F * ((float) Math.PI / 180F) + distance;
float f1 = Mth.cos(f) * (float) Math.PI * 0.15F;
float f2 = animationProgress - (float) entity.tickCount;
float f3 = animationProgress * 9.0F * ((float) Math.PI / 180F);
float f4 = Math.min(distance / 0.3F, 1.0F);
float f5 = 1.0F - f4;
float holdingItemAnimation = entity.getHoldingItemAnimationProgress(f2);
@ -68,12 +115,17 @@ public class AllayModel extends HierarchicalModel<Allay> implements ArmedModel {
this.left_wing.yRot = 0.61086524F - f1;
float f7 = f4 * 0.6981317F;
this.body.xRot = f7;
float f8 = Mth.lerp(holdingItemAnimation, f7, Mth.lerp(f4, (-(float)Math.PI / 3F), (-(float)Math.PI / 4F)));
this.root.y += (float)Math.cos(f3) * 0.25F * f5;
float f8 = Mth.lerp(
holdingItemAnimation,
f7,
Mth.lerp(f4, (-(float) Math.PI / 3F), (-(float) Math.PI / 4F))
);
this.root.y += (float) Math.cos(f3) * 0.25F * f5;
this.right_arm.xRot = f8;
this.left_arm.xRot = f8;
float f9 = f5 * (1.0F - holdingItemAnimation);
float f10 = 0.43633232F - Mth.cos(f3 + ((float)Math.PI * 1.5F)) * (float)Math.PI * 0.075F * f9;
float f10 = 0.43633232F
- Mth.cos(f3 + ((float) Math.PI * 1.5F)) * (float) Math.PI * 0.075F * f9;
this.left_arm.zRot = -f10;
this.right_arm.zRot = f10;
this.right_arm.yRot = 0.27925268F * holdingItemAnimation;
@ -81,7 +133,16 @@ public class AllayModel extends HierarchicalModel<Allay> implements ArmedModel {
}
@Override
public void renderToBuffer(PoseStack stack, VertexConsumer consumer, int i, int j, float f, float g, float h, float k) {
public void renderToBuffer(
PoseStack stack,
VertexConsumer consumer,
int i,
int j,
float f,
float g,
float h,
float k
) {
this.root.render(stack, consumer, i, j);
}

View file

@ -28,7 +28,15 @@ public class ChestBoatModel extends ListModel<MangroveBoat> {
this.rightPaddle = root.getChild("right_paddle");
this.waterPatch = root.getChild("water_patch");
ImmutableList.Builder<ModelPart> builder = new ImmutableList.Builder<>();
builder.add(root.getChild("bottom"), root.getChild("back"), root.getChild("front"), root.getChild("right"), root.getChild("left"), this.leftPaddle, this.rightPaddle);
builder.add(
root.getChild("bottom"),
root.getChild("back"),
root.getChild("front"),
root.getChild("right"),
root.getChild("left"),
this.leftPaddle,
this.rightPaddle
);
if (chest) {
builder.add(root.getChild("chest_bottom"));
builder.add(root.getChild("chest_lid"));
@ -41,25 +49,100 @@ public class ChestBoatModel extends ListModel<MangroveBoat> {
public static LayerDefinition createBodyModel(boolean chested) {
MeshDefinition mesh = new MeshDefinition();
PartDefinition part = mesh.getRoot();
part.addOrReplaceChild("bottom", CubeListBuilder.create().texOffs(0, 0).addBox(-14.0F, -9.0F, -3.0F, 28.0F, 16.0F, 3.0F), PartPose.offsetAndRotation(0.0F, 3.0F, 1.0F, 1.5707964F, 0.0F, 0.0F));
part.addOrReplaceChild("back", CubeListBuilder.create().texOffs(0, 19).addBox(-13.0F, -7.0F, -1.0F, 18.0F, 6.0F, 2.0F), PartPose.offsetAndRotation(-15.0F, 4.0F, 4.0F, 0.0F, 4.712389F, 0.0F));
part.addOrReplaceChild("front", CubeListBuilder.create().texOffs(0, 27).addBox(-8.0F, -7.0F, -1.0F, 16.0F, 6.0F, 2.0F), PartPose.offsetAndRotation(15.0F, 4.0F, 0.0F, 0.0F, 1.5707964F, 0.0F));
part.addOrReplaceChild("right", CubeListBuilder.create().texOffs(0, 35).addBox(-14.0F, -7.0F, -1.0F, 28.0F, 6.0F, 2.0F), PartPose.offsetAndRotation(0.0F, 4.0F, -9.0F, 0.0F, 3.1415927F, 0.0F));
part.addOrReplaceChild("left", CubeListBuilder.create().texOffs(0, 43).addBox(-14.0F, -7.0F, -1.0F, 28.0F, 6.0F, 2.0F), PartPose.offset(0.0F, 4.0F, 9.0F));
part.addOrReplaceChild(
"bottom",
CubeListBuilder.create().texOffs(0, 0).addBox(
-14.0F, -9.0F, -3.0F, 28.0F, 16.0F, 3.0F
),
PartPose.offsetAndRotation(0.0F, 3.0F, 1.0F, 1.5707964F, 0.0F, 0.0F)
);
part.addOrReplaceChild(
"back",
CubeListBuilder.create().texOffs(0, 19).addBox(
-13.0F, -7.0F, -1.0F, 18.0F, 6.0F, 2.0F
),
PartPose.offsetAndRotation(-15.0F, 4.0F, 4.0F, 0.0F, 4.712389F, 0.0F)
);
part.addOrReplaceChild(
"front",
CubeListBuilder.create().texOffs(0, 27).addBox(
-8.0F, -7.0F, -1.0F, 16.0F, 6.0F, 2.0F
),
PartPose.offsetAndRotation(15.0F, 4.0F, 0.0F, 0.0F, 1.5707964F, 0.0F)
);
part.addOrReplaceChild(
"right",
CubeListBuilder.create().texOffs(0, 35).addBox(
-14.0F, -7.0F, -1.0F, 28.0F, 6.0F, 2.0F
),
PartPose.offsetAndRotation(0.0F, 4.0F, -9.0F, 0.0F, 3.1415927F, 0.0F)
);
part.addOrReplaceChild(
"left",
CubeListBuilder.create().texOffs(0, 43).addBox(
-14.0F, -7.0F, -1.0F, 28.0F, 6.0F, 2.0F
),
PartPose.offset(0.0F, 4.0F, 9.0F)
);
if (chested) {
part.addOrReplaceChild("chest_bottom", CubeListBuilder.create().texOffs(0, 76).addBox(0.0f, 0.0f, 0.0f, 12.0f, 8.0f, 12.0f), PartPose.offsetAndRotation(-2.0f, -5.0f, -6.0f, 0.0f, -1.5707964f, 0.0f));
part.addOrReplaceChild("chest_lid", CubeListBuilder.create().texOffs(0, 59).addBox(0.0f, 0.0f, 0.0f, 12.0f, 4.0f, 12.0f), PartPose.offsetAndRotation(-2.0f, -9.0f, -6.0f, 0.0f, -1.5707964f, 0.0f));
part.addOrReplaceChild("chest_lock", CubeListBuilder.create().texOffs(0, 59).addBox(0.0f, 0.0f, 0.0f, 2.0f, 4.0f, 1.0f), PartPose.offsetAndRotation(-1.0f, -6.0f, -1.0f, 0.0f, -1.5707964f, 0.0f));
part.addOrReplaceChild(
"chest_bottom",
CubeListBuilder.create().texOffs(0, 76).addBox(
0.0f, 0.0f, 0.0f, 12.0f, 8.0f, 12.0f
),
PartPose.offsetAndRotation(-2.0f, -5.0f, -6.0f, 0.0f, -1.5707964f, 0.0f)
);
part.addOrReplaceChild(
"chest_lid",
CubeListBuilder.create().texOffs(0, 59).addBox(
0.0f, 0.0f, 0.0f, 12.0f, 4.0f, 12.0f
),
PartPose.offsetAndRotation(-2.0f, -9.0f, -6.0f, 0.0f, -1.5707964f, 0.0f)
);
part.addOrReplaceChild(
"chest_lock",
CubeListBuilder.create().texOffs(0, 59).addBox(
0.0f, 0.0f, 0.0f, 2.0f, 4.0f, 1.0f
),
PartPose.offsetAndRotation(-1.0f, -6.0f, -1.0f, 0.0f, -1.5707964f, 0.0f)
);
}
part.addOrReplaceChild("left_paddle", CubeListBuilder.create().texOffs(62, 0).addBox(-1.0F, 0.0F, -5.0F, 2.0F, 2.0F, 18.0F).addBox(-1.001F, -3.0F, 8.0F, 1.0F, 6.0F, 7.0F), PartPose.offsetAndRotation(3.0F, -5.0F, 9.0F, 0.0F, 0.0F, 0.19634955F));
part.addOrReplaceChild("right_paddle", CubeListBuilder.create().texOffs(62, 20).addBox(-1.0F, 0.0F, -5.0F, 2.0F, 2.0F, 18.0F).addBox(0.001F, -3.0F, 8.0F, 1.0F, 6.0F, 7.0F), PartPose.offsetAndRotation(3.0F, -5.0F, -9.0F, 0.0F, 3.1415927F, 0.19634955F));
part.addOrReplaceChild("water_patch", CubeListBuilder.create().texOffs(0, 0).addBox(-14.0F, -9.0F, -3.0F, 28.0F, 16.0F, 3.0F), PartPose.offsetAndRotation(0.0F, -3.0F, 1.0F, 1.5707964F, 0.0F, 0.0F));
part.addOrReplaceChild(
"left_paddle",
CubeListBuilder.create()
.texOffs(62, 0)
.addBox(-1.0F, 0.0F, -5.0F, 2.0F, 2.0F, 18.0F)
.addBox(-1.001F, -3.0F, 8.0F, 1.0F, 6.0F, 7.0F),
PartPose.offsetAndRotation(3.0F, -5.0F, 9.0F, 0.0F, 0.0F, 0.19634955F)
);
part.addOrReplaceChild(
"right_paddle",
CubeListBuilder.create()
.texOffs(62, 20)
.addBox(-1.0F, 0.0F, -5.0F, 2.0F, 2.0F, 18.0F)
.addBox(0.001F, -3.0F, 8.0F, 1.0F, 6.0F, 7.0F),
PartPose.offsetAndRotation(3.0F, -5.0F, -9.0F, 0.0F, 3.1415927F, 0.19634955F)
);
part.addOrReplaceChild(
"water_patch",
CubeListBuilder.create().texOffs(0, 0).addBox(
-14.0F, -9.0F, -3.0F, 28.0F, 16.0F, 3.0F
),
PartPose.offsetAndRotation(0.0F, -3.0F, 1.0F, 1.5707964F, 0.0F, 0.0F)
);
return LayerDefinition.create(mesh, 128, chested ? 128 : 64);
}
@Override
public void setupAnim(MangroveBoat boat, float angle, float distance, float animationProgress, float yaw, float pitch) {
public void setupAnim(
MangroveBoat boat,
float angle,
float distance,
float animationProgress,
float yaw,
float pitch
) {
animatePaddle(boat, 0, this.leftPaddle, angle);
animatePaddle(boat, 1, this.rightPaddle, angle);
}
@ -72,14 +155,21 @@ public class ChestBoatModel extends ListModel<MangroveBoat> {
return this.waterPatch;
}
private static void animatePaddle(MangroveBoat boat, int sigma, ModelPart part, float angle) {
private static void
animatePaddle(MangroveBoat boat, int sigma, ModelPart part, float angle) {
float time = boat.getRowingTime(sigma, angle);
part.xRot = Mth.clampedLerp(-1.0471976F, -0.2617994F, (Mth.sin(-time) + 1.0F) / 2.0F);
part.yRot = Mth.clampedLerp(-0.7853982F, 0.7853982F, (Mth.sin(-time + 1.0F) + 1.0F) / 2.0F);
if (sigma == 1) part.yRot = (float)Math.PI - part.yRot;
part.xRot
= Mth.clampedLerp(-1.0471976F, -0.2617994F, (Mth.sin(-time) + 1.0F) / 2.0F);
part.yRot = Mth.clampedLerp(
-0.7853982F, 0.7853982F, (Mth.sin(-time + 1.0F) + 1.0F) / 2.0F
);
if (sigma == 1)
part.yRot = (float) Math.PI - part.yRot;
}
public static ModelLayerLocation createChestBoat(Boat.Type type) {
return new ModelLayerLocation(new ResourceLocation("chest_boat/" + type.getName()), "main");
return new ModelLayerLocation(
new ResourceLocation("chest_boat/" + type.getName()), "main"
);
}
}

View file

@ -40,35 +40,156 @@ public class FrogModel<T extends Frog> extends AnimatedModel<T> {
public static LayerDefinition createBodyLayer() {
MeshDefinition mesh = new MeshDefinition();
PartDefinition root = mesh.getRoot();
PartDefinition bone = root.addOrReplaceChild("root", CubeListBuilder.create(), PartPose.offset(0.0f, 24.0f, 0.0f));
PartDefinition body = bone.addOrReplaceChild("body", CubeListBuilder.create().texOffs(3, 1).addBox(-3.5f, -2.0f, -8.0f, 7.0f, 3.0f, 9.0f).texOffs(23, 22).addBox(-3.5f, -1.0f, -8.0f, 7.0f, 0.0f, 9.0f), PartPose.offset(0.0f, -2.0f, 4.0f));
PartDefinition head = body.addOrReplaceChild("head", CubeListBuilder.create().texOffs(23, 13).addBox(-3.5f, -1.0f, -7.0f, 7.0f, 0.0f, 9.0f).texOffs(0, 13).addBox(-3.5f, -2.0f, -7.0f, 7.0f, 3.0f, 9.0f), PartPose.offset(0.0f, -2.0f, -1.0f));
PartDefinition eyes = head.addOrReplaceChild("eyes", CubeListBuilder.create(), PartPose.offset(-0.5f, 0.0f, 2.0f));
eyes.addOrReplaceChild("right_eye", CubeListBuilder.create().texOffs(0, 0).addBox(-1.5f, -1.0f, -1.5f, 3.0f, 2.0f, 3.0f), PartPose.offset(-1.5f, -3.0f, -6.5f));
eyes.addOrReplaceChild("left_eye", CubeListBuilder.create().texOffs(0, 5).addBox(-1.5f, -1.0f, -1.5f, 3.0f, 2.0f, 3.0f), PartPose.offset(2.5f, -3.0f, -6.5f));
body.addOrReplaceChild("croaking_body", CubeListBuilder.create().texOffs(26, 5).addBox(-3.5f, -0.1f, -2.9f, 7.0f, 2.0f, 3.0f, new CubeDeformation(-0.1f)), PartPose.offset(0.0f, -1.0f, -5.0f));
body.addOrReplaceChild("tongue", CubeListBuilder.create().texOffs(17, 13).addBox(-2.0f, 0.0f, -7.1f, 4.0f, 0.0f, 7.0f), PartPose.offset(0.0f, -1.01f, 1.0f));
PartDefinition left_arm = body.addOrReplaceChild("left_arm", CubeListBuilder.create().texOffs(0, 32).addBox(-1.0f, 0.0f, -1.0f, 2.0f, 3.0f, 3.0f), PartPose.offset(4.0f, -1.0f, -6.5f));
left_arm.addOrReplaceChild("left_hand", CubeListBuilder.create().texOffs(18, 40).addBox(-4.0f, 0.01f, -4.0f, 8.0f, 0.0f, 8.0f), PartPose.offset(0.0f, 3.0f, -1.0f));
PartDefinition right_arm = body.addOrReplaceChild("right_arm", CubeListBuilder.create().texOffs(0, 38).addBox(-1.0f, 0.0f, -1.0f, 2.0f, 3.0f, 3.0f), PartPose.offset(-4.0f, -1.0f, -6.5f));
right_arm.addOrReplaceChild("right_hand", CubeListBuilder.create().texOffs(2, 40).addBox(-4.0f, 0.01f, -5.0f, 8.0f, 0.0f, 8.0f), PartPose.offset(0.0f, 3.0f, 0.0f));
PartDefinition left_leg = bone.addOrReplaceChild("left_leg", CubeListBuilder.create().texOffs(14, 25).addBox(-1.0f, 0.0f, -2.0f, 3.0f, 3.0f, 4.0f), PartPose.offset(3.5f, -3.0f, 4.0f));
left_leg.addOrReplaceChild("left_foot", CubeListBuilder.create().texOffs(2, 32).addBox(-4.0f, 0.01f, -4.0f, 8.0f, 0.0f, 8.0f), PartPose.offset(2.0f, 3.0f, 0.0f));
PartDefinition right_leg = bone.addOrReplaceChild("right_leg", CubeListBuilder.create().texOffs(0, 25).addBox(-2.0f, 0.0f, -2.0f, 3.0f, 3.0f, 4.0f), PartPose.offset(-3.5f, -3.0f, 4.0f));
right_leg.addOrReplaceChild("right_foot", CubeListBuilder.create().texOffs(18, 32).addBox(-4.0f, 0.01f, -4.0f, 8.0f, 0.0f, 8.0f), PartPose.offset(-2.0f, 3.0f, 0.0f));
PartDefinition bone = root.addOrReplaceChild(
"root", CubeListBuilder.create(), PartPose.offset(0.0f, 24.0f, 0.0f)
);
PartDefinition body = bone.addOrReplaceChild(
"body",
CubeListBuilder.create()
.texOffs(3, 1)
.addBox(-3.5f, -2.0f, -8.0f, 7.0f, 3.0f, 9.0f)
.texOffs(23, 22)
.addBox(-3.5f, -1.0f, -8.0f, 7.0f, 0.0f, 9.0f),
PartPose.offset(0.0f, -2.0f, 4.0f)
);
PartDefinition head = body.addOrReplaceChild(
"head",
CubeListBuilder.create()
.texOffs(23, 13)
.addBox(-3.5f, -1.0f, -7.0f, 7.0f, 0.0f, 9.0f)
.texOffs(0, 13)
.addBox(-3.5f, -2.0f, -7.0f, 7.0f, 3.0f, 9.0f),
PartPose.offset(0.0f, -2.0f, -1.0f)
);
PartDefinition eyes = head.addOrReplaceChild(
"eyes", CubeListBuilder.create(), PartPose.offset(-0.5f, 0.0f, 2.0f)
);
eyes.addOrReplaceChild(
"right_eye",
CubeListBuilder.create().texOffs(0, 0).addBox(
-1.5f, -1.0f, -1.5f, 3.0f, 2.0f, 3.0f
),
PartPose.offset(-1.5f, -3.0f, -6.5f)
);
eyes.addOrReplaceChild(
"left_eye",
CubeListBuilder.create().texOffs(0, 5).addBox(
-1.5f, -1.0f, -1.5f, 3.0f, 2.0f, 3.0f
),
PartPose.offset(2.5f, -3.0f, -6.5f)
);
body.addOrReplaceChild(
"croaking_body",
CubeListBuilder.create().texOffs(26, 5).addBox(
-3.5f, -0.1f, -2.9f, 7.0f, 2.0f, 3.0f, new CubeDeformation(-0.1f)
),
PartPose.offset(0.0f, -1.0f, -5.0f)
);
body.addOrReplaceChild(
"tongue",
CubeListBuilder.create().texOffs(17, 13).addBox(
-2.0f, 0.0f, -7.1f, 4.0f, 0.0f, 7.0f
),
PartPose.offset(0.0f, -1.01f, 1.0f)
);
PartDefinition left_arm = body.addOrReplaceChild(
"left_arm",
CubeListBuilder.create().texOffs(0, 32).addBox(
-1.0f, 0.0f, -1.0f, 2.0f, 3.0f, 3.0f
),
PartPose.offset(4.0f, -1.0f, -6.5f)
);
left_arm.addOrReplaceChild(
"left_hand",
CubeListBuilder.create().texOffs(18, 40).addBox(
-4.0f, 0.01f, -4.0f, 8.0f, 0.0f, 8.0f
),
PartPose.offset(0.0f, 3.0f, -1.0f)
);
PartDefinition right_arm = body.addOrReplaceChild(
"right_arm",
CubeListBuilder.create().texOffs(0, 38).addBox(
-1.0f, 0.0f, -1.0f, 2.0f, 3.0f, 3.0f
),
PartPose.offset(-4.0f, -1.0f, -6.5f)
);
right_arm.addOrReplaceChild(
"right_hand",
CubeListBuilder.create().texOffs(2, 40).addBox(
-4.0f, 0.01f, -5.0f, 8.0f, 0.0f, 8.0f
),
PartPose.offset(0.0f, 3.0f, 0.0f)
);
PartDefinition left_leg = bone.addOrReplaceChild(
"left_leg",
CubeListBuilder.create().texOffs(14, 25).addBox(
-1.0f, 0.0f, -2.0f, 3.0f, 3.0f, 4.0f
),
PartPose.offset(3.5f, -3.0f, 4.0f)
);
left_leg.addOrReplaceChild(
"left_foot",
CubeListBuilder.create().texOffs(2, 32).addBox(
-4.0f, 0.01f, -4.0f, 8.0f, 0.0f, 8.0f
),
PartPose.offset(2.0f, 3.0f, 0.0f)
);
PartDefinition right_leg = bone.addOrReplaceChild(
"right_leg",
CubeListBuilder.create().texOffs(0, 25).addBox(
-2.0f, 0.0f, -2.0f, 3.0f, 3.0f, 4.0f
),
PartPose.offset(-3.5f, -3.0f, 4.0f)
);
right_leg.addOrReplaceChild(
"right_foot",
CubeListBuilder.create().texOffs(18, 32).addBox(
-4.0f, 0.01f, -4.0f, 8.0f, 0.0f, 8.0f
),
PartPose.offset(-2.0f, 3.0f, 0.0f)
);
return LayerDefinition.create(mesh, 48, 48);
}
@Override
public void setupAnim(T entity, float angle, float distance, float animationProgress, float yaw, float pitch) {
public void setupAnim(
T entity,
float angle,
float distance,
float animationProgress,
float yaw,
float pitch
) {
this.root.getAllParts().forEach(Animated::resetToDefault);
float speedMultiplier = Math.min((float)entity.getDeltaMovement().lengthSqr() * 200.0F, 8.0F);
this.animate(entity.longJumpingAnimationState, FrogAnimations.LONG_JUMPING, animationProgress);
this.animate(entity.croakingAnimationState, FrogAnimations.CROAKING, animationProgress);
this.animate(entity.usingTongueAnimationState, FrogAnimations.USING_TONGUE, animationProgress);
this.animate(entity.walkingAnimationState, FrogAnimations.WALKING, animationProgress, speedMultiplier);
this.animate(entity.swimmingAnimationState, FrogAnimations.SWIMMING, animationProgress);
this.animate(entity.idlingInWaterAnimationState, FrogAnimations.IDLING_IN_WATER, animationProgress);
float speedMultiplier
= Math.min((float) entity.getDeltaMovement().lengthSqr() * 200.0F, 8.0F);
this.animate(
entity.longJumpingAnimationState,
FrogAnimations.LONG_JUMPING,
animationProgress
);
this.animate(
entity.croakingAnimationState, FrogAnimations.CROAKING, animationProgress
);
this.animate(
entity.usingTongueAnimationState,
FrogAnimations.USING_TONGUE,
animationProgress
);
this.animate(
entity.walkingAnimationState,
FrogAnimations.WALKING,
animationProgress,
speedMultiplier
);
this.animate(
entity.swimmingAnimationState, FrogAnimations.SWIMMING, animationProgress
);
this.animate(
entity.idlingInWaterAnimationState,
FrogAnimations.IDLING_IN_WATER,
animationProgress
);
this.croakingBody.visible = entity.croakingAnimationState.isRunning();
}

View file

@ -24,8 +24,20 @@ public class TadpoleModel<T extends Tadpole> extends AgeableListModel<T> {
public static LayerDefinition createBodyLayer() {
MeshDefinition mesh = new MeshDefinition();
PartDefinition root = mesh.getRoot();
root.addOrReplaceChild("body", CubeListBuilder.create().texOffs(0, 0).addBox(-1.5F, -1.0F, 0.0F, 3.0F, 2.0F, 3.0F), PartPose.offset(0.0F, 22.0F, -3.0F));
root.addOrReplaceChild("tail", CubeListBuilder.create().texOffs(0, 0).addBox(0.0F, -1.0F, 0.0F, 0.0F, 2.0F, 7.0F), PartPose.offset(0.0F, 22.0F, 0.0F));
root.addOrReplaceChild(
"body",
CubeListBuilder.create().texOffs(0, 0).addBox(
-1.5F, -1.0F, 0.0F, 3.0F, 2.0F, 3.0F
),
PartPose.offset(0.0F, 22.0F, -3.0F)
);
root.addOrReplaceChild(
"tail",
CubeListBuilder.create().texOffs(0, 0).addBox(
0.0F, -1.0F, 0.0F, 0.0F, 2.0F, 7.0F
),
PartPose.offset(0.0F, 22.0F, 0.0F)
);
return LayerDefinition.create(mesh, 16, 16);
}
@ -40,9 +52,15 @@ public class TadpoleModel<T extends Tadpole> extends AgeableListModel<T> {
}
@Override
public void setupAnim(T entity, float angle, float distance, float animationProgress, float yaw, float pitch) {
public void setupAnim(
T entity,
float angle,
float distance,
float animationProgress,
float yaw,
float pitch
) {
float angles = entity.isInWater() ? 1.0F : 1.5F;
this.tail.yRot = -angles * 0.25F * Mth.sin(0.3F * animationProgress);
}
}

View file

@ -1,5 +1,7 @@
package com.cursedcauldron.wildbackport.client.render.model;
import java.util.List;
import com.cursedcauldron.wildbackport.client.animation.WardenAnimations;
import com.cursedcauldron.wildbackport.client.animation.api.Animated;
import com.cursedcauldron.wildbackport.client.animation.api.AnimatedModel;
@ -14,8 +16,6 @@ import net.minecraft.client.model.geom.builders.PartDefinition;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.util.Mth;
import java.util.List;
//<>
public class WardenModel<T extends Warden> extends AnimatedModel<T> {
@ -52,46 +52,133 @@ public class WardenModel<T extends Warden> extends AnimatedModel<T> {
this.leftRibcage = this.body.getChild("left_ribcage");
this.tendrils = ImmutableList.of(this.leftTendril, this.rightTendril);
this.justBody = ImmutableList.of(this.body);
this.headAndLimbs = ImmutableList.of(this.head, this.leftArm, this.rightArm, this.leftLeg, this.rightLeg);
this.bodyHeadAndLimbs = ImmutableList.of(this.body, this.head, this.leftArm, this.rightArm, this.leftLeg, this.rightLeg);
this.headAndLimbs = ImmutableList.of(
this.head, this.leftArm, this.rightArm, this.leftLeg, this.rightLeg
);
this.bodyHeadAndLimbs = ImmutableList.of(
this.body, this.head, this.leftArm, this.rightArm, this.leftLeg, this.rightLeg
);
}
public static LayerDefinition createBodyLayer() {
MeshDefinition mesh = new MeshDefinition();
PartDefinition root = mesh.getRoot();
PartDefinition bone = root.addOrReplaceChild("bone", CubeListBuilder.create(), PartPose.offset(0.0f, 24.0f, 0.0f));
PartDefinition body = bone.addOrReplaceChild("body", CubeListBuilder.create().texOffs(0, 0).addBox(-9.0f, -13.0f, -4.0f, 18.0f, 21.0f, 11.0f), PartPose.offset(0.0f, -21.0f, 0.0f));
body.addOrReplaceChild("right_ribcage", CubeListBuilder.create().texOffs(90, 11).addBox(-2.0f, -11.0f, -0.1f, 9.0f, 21.0f, 0.0f), PartPose.offset(-7.0f, -2.0f, -4.0f));
body.addOrReplaceChild("left_ribcage", CubeListBuilder.create().texOffs(90, 11).mirror().addBox(-7.0f, -11.0f, -0.1f, 9.0f, 21.0f, 0.0f).mirror(false), PartPose.offset(7.0f, -2.0f, -4.0f));
PartDefinition head = body.addOrReplaceChild("head", CubeListBuilder.create().texOffs(0, 32).addBox(-8.0f, -16.0f, -5.0f, 16.0f, 16.0f, 10.0f), PartPose.offset(0.0f, -13.0f, 0.0f));
head.addOrReplaceChild("right_tendril", CubeListBuilder.create().texOffs(52, 32).addBox(-16.0f, -13.0f, 0.0f, 16.0f, 16.0f, 0.0f), PartPose.offset(-8.0f, -12.0f, 0.0f));
head.addOrReplaceChild("left_tendril", CubeListBuilder.create().texOffs(58, 0).addBox(0.0f, -13.0f, 0.0f, 16.0f, 16.0f, 0.0f), PartPose.offset(8.0f, -12.0f, 0.0f));
body.addOrReplaceChild("right_arm", CubeListBuilder.create().texOffs(44, 50).addBox(-4.0f, 0.0f, -4.0f, 8.0f, 28.0f, 8.0f), PartPose.offset(-13.0f, -13.0f, 1.0f));
body.addOrReplaceChild("left_arm", CubeListBuilder.create().texOffs(0, 58).addBox(-4.0f, 0.0f, -4.0f, 8.0f, 28.0f, 8.0f), PartPose.offset(13.0f, -13.0f, 1.0f));
bone.addOrReplaceChild("right_leg", CubeListBuilder.create().texOffs(76, 48).addBox(-3.1f, 0.0f, -3.0f, 6.0f, 13.0f, 6.0f), PartPose.offset(-5.9f, -13.0f, 0.0f));
bone.addOrReplaceChild("left_leg", CubeListBuilder.create().texOffs(76, 76).addBox(-2.9f, 0.0f, -3.0f, 6.0f, 13.0f, 6.0f), PartPose.offset(5.9f, -13.0f, 0.0f));
PartDefinition bone = root.addOrReplaceChild(
"bone", CubeListBuilder.create(), PartPose.offset(0.0f, 24.0f, 0.0f)
);
PartDefinition body = bone.addOrReplaceChild(
"body",
CubeListBuilder.create().texOffs(0, 0).addBox(
-9.0f, -13.0f, -4.0f, 18.0f, 21.0f, 11.0f
),
PartPose.offset(0.0f, -21.0f, 0.0f)
);
body.addOrReplaceChild(
"right_ribcage",
CubeListBuilder.create().texOffs(90, 11).addBox(
-2.0f, -11.0f, -0.1f, 9.0f, 21.0f, 0.0f
),
PartPose.offset(-7.0f, -2.0f, -4.0f)
);
body.addOrReplaceChild(
"left_ribcage",
CubeListBuilder.create()
.texOffs(90, 11)
.mirror()
.addBox(-7.0f, -11.0f, -0.1f, 9.0f, 21.0f, 0.0f)
.mirror(false),
PartPose.offset(7.0f, -2.0f, -4.0f)
);
PartDefinition head = body.addOrReplaceChild(
"head",
CubeListBuilder.create().texOffs(0, 32).addBox(
-8.0f, -16.0f, -5.0f, 16.0f, 16.0f, 10.0f
),
PartPose.offset(0.0f, -13.0f, 0.0f)
);
head.addOrReplaceChild(
"right_tendril",
CubeListBuilder.create().texOffs(52, 32).addBox(
-16.0f, -13.0f, 0.0f, 16.0f, 16.0f, 0.0f
),
PartPose.offset(-8.0f, -12.0f, 0.0f)
);
head.addOrReplaceChild(
"left_tendril",
CubeListBuilder.create().texOffs(58, 0).addBox(
0.0f, -13.0f, 0.0f, 16.0f, 16.0f, 0.0f
),
PartPose.offset(8.0f, -12.0f, 0.0f)
);
body.addOrReplaceChild(
"right_arm",
CubeListBuilder.create().texOffs(44, 50).addBox(
-4.0f, 0.0f, -4.0f, 8.0f, 28.0f, 8.0f
),
PartPose.offset(-13.0f, -13.0f, 1.0f)
);
body.addOrReplaceChild(
"left_arm",
CubeListBuilder.create().texOffs(0, 58).addBox(
-4.0f, 0.0f, -4.0f, 8.0f, 28.0f, 8.0f
),
PartPose.offset(13.0f, -13.0f, 1.0f)
);
bone.addOrReplaceChild(
"right_leg",
CubeListBuilder.create().texOffs(76, 48).addBox(
-3.1f, 0.0f, -3.0f, 6.0f, 13.0f, 6.0f
),
PartPose.offset(-5.9f, -13.0f, 0.0f)
);
bone.addOrReplaceChild(
"left_leg",
CubeListBuilder.create().texOffs(76, 76).addBox(
-2.9f, 0.0f, -3.0f, 6.0f, 13.0f, 6.0f
),
PartPose.offset(5.9f, -13.0f, 0.0f)
);
return LayerDefinition.create(mesh, 128, 128);
}
@Override
public void setupAnim(T entity, float angle, float distance, float animationProgress, float yaw, float pitch) {
public void setupAnim(
T entity,
float angle,
float distance,
float animationProgress,
float yaw,
float pitch
) {
this.root.getAllParts().forEach(Animated::resetToDefault);
float tickDelta = animationProgress - (float)entity.tickCount;
float tickDelta = animationProgress - (float) entity.tickCount;
this.setHeadAngle(yaw, pitch);
this.setLimbAngles(angle, distance);
this.setHeadAndBodyAngles(animationProgress);
this.setTendrilPitches(entity, animationProgress, tickDelta);
this.animate(entity.attackingAnimationState, WardenAnimations.ATTACKING, animationProgress);
this.animate(entity.sonicBoomAnimationState, WardenAnimations.SONIC_BOOM, animationProgress);
this.animate(entity.diggingAnimationState, WardenAnimations.DIGGING, animationProgress);
this.animate(entity.emergingAnimationState, WardenAnimations.EMERGING, animationProgress);
this.animate(entity.roaringAnimationState, WardenAnimations.ROARING, animationProgress);
this.animate(entity.sniffingAnimationState, WardenAnimations.SNIFFING, animationProgress);
this.animate(
entity.attackingAnimationState, WardenAnimations.ATTACKING, animationProgress
);
this.animate(
entity.sonicBoomAnimationState, WardenAnimations.SONIC_BOOM, animationProgress
);
this.animate(
entity.diggingAnimationState, WardenAnimations.DIGGING, animationProgress
);
this.animate(
entity.emergingAnimationState, WardenAnimations.EMERGING, animationProgress
);
this.animate(
entity.roaringAnimationState, WardenAnimations.ROARING, animationProgress
);
this.animate(
entity.sniffingAnimationState, WardenAnimations.SNIFFING, animationProgress
);
}
private void setHeadAngle(float yaw, float pitch) {
this.head.xRot = pitch * ((float)Math.PI / 180);
this.head.yRot = yaw * ((float)Math.PI / 180);
this.head.xRot = pitch * ((float) Math.PI / 180);
this.head.yRot = yaw * ((float) Math.PI / 180);
}
private void setHeadAndBodyAngles(float animationProgress) {
@ -115,7 +202,7 @@ public class WardenModel<T extends Warden> extends AnimatedModel<T> {
this.body.zRot = 0.1F * sin * roll;
this.body.xRot = 1.0F * cos * pitch;
this.leftLeg.xRot = 1.0F * cos * roll;
this.rightLeg.xRot = 1.0F * Mth.cos(mod + (float)Math.PI) * roll;
this.rightLeg.xRot = 1.0F * Mth.cos(mod + (float) Math.PI) * roll;
this.leftArm.xRot = -(0.8F * cos * roll);
this.leftArm.zRot = 0.0F;
this.rightArm.xRot = -(0.8F * sin * roll);
@ -135,7 +222,9 @@ public class WardenModel<T extends Warden> extends AnimatedModel<T> {
}
private void setTendrilPitches(T warden, float animationProgress, float tickDelta) {
float pitch = warden.getTendrilPitch(tickDelta) * (float)(Math.cos((double)animationProgress * 2.25D) * Math.PI * (double)0.1F);
float pitch = warden.getTendrilPitch(tickDelta)
* (float
) (Math.cos((double) animationProgress * 2.25D) * Math.PI * (double) 0.1F);
this.leftTendril.xRot = pitch;
this.rightTendril.xRot = -pitch;
}

View file

@ -1,10 +1,10 @@
package com.cursedcauldron.wildbackport.client.sound;
import java.util.function.Supplier;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.world.level.block.SoundType;
import java.util.function.Supplier;
public class CoreSoundType extends SoundType {
private final Supplier<SoundEvent> breakSound;
private final Supplier<SoundEvent> stepSound;
@ -13,7 +13,13 @@ public class CoreSoundType extends SoundType {
private final Supplier<SoundEvent> fallSound;
@SuppressWarnings("all")
public CoreSoundType(Supplier<SoundEvent> breakSound, Supplier<SoundEvent> stepSound, Supplier<SoundEvent> placeSound, Supplier<SoundEvent> hitSound, Supplier<SoundEvent> fallSound) {
public CoreSoundType(
Supplier<SoundEvent> breakSound,
Supplier<SoundEvent> stepSound,
Supplier<SoundEvent> placeSound,
Supplier<SoundEvent> hitSound,
Supplier<SoundEvent> fallSound
) {
super(1.0F, 1.0F, null, null, null, null, null);
this.breakSound = breakSound;
this.stepSound = stepSound;

View file

@ -7,9 +7,9 @@ import com.cursedcauldron.wildbackport.common.entities.Warden;
import com.cursedcauldron.wildbackport.common.entities.access.Recovery;
import com.cursedcauldron.wildbackport.common.items.CompassItemPropertyFunction;
import com.cursedcauldron.wildbackport.common.registry.WBItems;
import com.cursedcauldron.wildbackport.common.worldgen.structure.StructureGeneration;
import com.cursedcauldron.wildbackport.common.registry.entity.WBEntityTypes;
import com.cursedcauldron.wildbackport.common.registry.worldgen.WBWorldGeneration;
import com.cursedcauldron.wildbackport.common.worldgen.structure.StructureGeneration;
import com.cursedcauldron.wildbackport.core.api.MobRegistry;
import com.cursedcauldron.wildbackport.core.api.worldgen.BiomeModifier;
import net.minecraft.client.renderer.item.ItemProperties;

View file

@ -53,7 +53,9 @@ public class VanillaIntegration {
// Strippables
addStrippable(WBBlocks.MANGROVE_LOG.get(), WBBlocks.STRIPPED_MANGROVE_LOG.get());
addStrippable(WBBlocks.MANGROVE_WOOD.get(), WBBlocks.STRIPPED_MANGROVE_WOOD.get());
addStrippable(
WBBlocks.MANGROVE_WOOD.get(), WBBlocks.STRIPPED_MANGROVE_WOOD.get()
);
// Turning Dirt into Mud
Interactions.addRightClick(context -> {
@ -62,18 +64,40 @@ public class VanillaIntegration {
Player player = context.getPlayer();
ItemStack stack = context.getItemInHand();
BlockState state = level.getBlockState(pos);
if (player != null && context.getClickedFace() != Direction.DOWN && state.is(WBBlockTags.CONVERTABLE_TO_MUD) && PotionUtils.getPotion(stack) == Potions.WATER) {
level.playSound(null, pos, SoundEvents.GENERIC_SPLASH, SoundSource.PLAYERS, 1.0F, 1.0F);
player.setItemInHand(context.getHand(), ItemUtils.createFilledResult(stack, player, new ItemStack(Items.GLASS_BOTTLE)));
if (player != null && context.getClickedFace() != Direction.DOWN
&& state.is(WBBlockTags.CONVERTABLE_TO_MUD)
&& PotionUtils.getPotion(stack) == Potions.WATER) {
level.playSound(
null, pos, SoundEvents.GENERIC_SPLASH, SoundSource.PLAYERS, 1.0F, 1.0F
);
player.setItemInHand(
context.getHand(),
ItemUtils.createFilledResult(
stack, player, new ItemStack(Items.GLASS_BOTTLE)
)
);
player.awardStat(Stats.ITEM_USED.get(stack.getItem()));
if (!level.isClientSide()) {
for (int i = 0; i < 5; i++) {
((ServerLevel)level).sendParticles(ParticleTypes.SPLASH, (double)pos.getX() + level.random.nextDouble(), pos.getY() + 1, (double)pos.getZ() + level.random.nextDouble(), 1, 0.0D, 0.0D, 0.0D, 1.0D);
((ServerLevel) level)
.sendParticles(
ParticleTypes.SPLASH,
(double) pos.getX() + level.random.nextDouble(),
pos.getY() + 1,
(double) pos.getZ() + level.random.nextDouble(),
1,
0.0D,
0.0D,
0.0D,
1.0D
);
}
}
level.playSound(null, pos, SoundEvents.BOTTLE_EMPTY, SoundSource.BLOCKS, 1.0F, 1.0F);
level.playSound(
null, pos, SoundEvents.BOTTLE_EMPTY, SoundSource.BLOCKS, 1.0F, 1.0F
);
level.gameEvent(GameEvent.FLUID_PLACE, pos);
level.setBlockAndUpdate(pos, WBBlocks.MUD.get().defaultBlockState());
return InteractionResult.sidedSuccess(level.isClientSide());
@ -83,27 +107,51 @@ public class VanillaIntegration {
});
DispenserBlock.registerBehavior(Items.POTION, new DefaultDispenseItemBehavior() {
private final DefaultDispenseItemBehavior behavior = new DefaultDispenseItemBehavior();
private final DefaultDispenseItemBehavior behavior
= new DefaultDispenseItemBehavior();
@Override protected ItemStack execute(BlockSource source, ItemStack stack) {
@Override
protected ItemStack execute(BlockSource source, ItemStack stack) {
if (PotionUtils.getPotion(stack) != Potions.WATER) {
return this.behavior.dispense(source, stack);
} else {
ServerLevel level = source.getLevel();
BlockPos sourcePos = source.getPos();
BlockPos dispenserPos = source.getPos().relative(source.getBlockState().getValue(DispenserBlock.FACING));
if (!level.getBlockState(dispenserPos).is(WBBlockTags.CONVERTABLE_TO_MUD)) {
BlockPos dispenserPos = source.getPos().relative(
source.getBlockState().getValue(DispenserBlock.FACING)
);
if (!level.getBlockState(dispenserPos)
.is(WBBlockTags.CONVERTABLE_TO_MUD)) {
return this.behavior.dispense(source, stack);
} else {
if (!level.isClientSide()) {
for (int i = 0; i < 5; i++) {
level.sendParticles(ParticleTypes.SPLASH, (double)sourcePos.getX() + level.random.nextDouble(), sourcePos.getY() + 1, (double)sourcePos.getZ() + level.random.nextDouble(), 1, 0.0D, 0.0D, 0.0D, 1.0D);
level.sendParticles(
ParticleTypes.SPLASH,
(double) sourcePos.getX() + level.random.nextDouble(),
sourcePos.getY() + 1,
(double) sourcePos.getZ() + level.random.nextDouble(),
1,
0.0D,
0.0D,
0.0D,
1.0D
);
}
}
level.playSound(null, sourcePos, SoundEvents.BOTTLE_EMPTY, SoundSource.BLOCKS, 1.0F, 1.0F);
level.playSound(
null,
sourcePos,
SoundEvents.BOTTLE_EMPTY,
SoundSource.BLOCKS,
1.0F,
1.0F
);
level.gameEvent(GameEvent.FLUID_PLACE, sourcePos);
level.setBlockAndUpdate(dispenserPos, WBBlocks.MUD.get().defaultBlockState());
level.setBlockAndUpdate(
dispenserPos, WBBlocks.MUD.get().defaultBlockState()
);
return new ItemStack(Items.GLASS_BOTTLE);
}
}
@ -112,7 +160,7 @@ public class VanillaIntegration {
}
public static void addFlammable(Block block, int flameOdds, int burnOdds) {
((FireBlockAccessor)Blocks.FIRE).callSetFlammable(block, flameOdds, burnOdds);
((FireBlockAccessor) Blocks.FIRE).callSetFlammable(block, flameOdds, burnOdds);
}
public static void addCompostable(ItemLike item, float chance) {

View file

@ -1,5 +1,7 @@
package com.cursedcauldron.wildbackport.common.blocks;
import java.util.Optional;
import com.cursedcauldron.wildbackport.common.registry.WBBlocks;
import com.cursedcauldron.wildbackport.common.tag.WBBlockTags;
import com.cursedcauldron.wildbackport.core.mixin.access.PointedDripstoneBlockAccessor;
@ -12,27 +14,39 @@ import net.minecraft.world.level.material.Fluid;
import net.minecraft.world.level.material.Fluids;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.Optional;
public record DrippingFluid(BlockPos pos, Fluid fluid, BlockState sourceState) {
public static void fillCauldron(BlockState state, ServerLevel world, BlockPos blockPos, CallbackInfo ci) {
Optional<DrippingFluid> fluidAbove = getFluidAboveStalactite(world, blockPos, state);
public static void fillCauldron(
BlockState state, ServerLevel world, BlockPos blockPos, CallbackInfo ci
) {
Optional<DrippingFluid> fluidAbove
= getFluidAboveStalactite(world, blockPos, state);
if (fluidAbove.isPresent()) {
Fluid fluid = fluidAbove.get().fluid;
if (fluidAbove.get().sourceState().is(WBBlockTags.MUD) && fluid == Fluids.WATER) {
world.setBlockAndUpdate(fluidAbove.get().pos, Blocks.CLAY.defaultBlockState());
if (fluidAbove.get().sourceState().is(WBBlockTags.MUD)
&& fluid == Fluids.WATER) {
world.setBlockAndUpdate(
fluidAbove.get().pos, Blocks.CLAY.defaultBlockState()
);
world.levelEvent(1504, blockPos, 0);
ci.cancel();
}
}
}
public static Optional<DrippingFluid> getFluidAboveStalactite(Level level, BlockPos pos, BlockState state) {
return !PointedDripstoneBlockAccessor.callIsStalactite(state) ? Optional.empty() : PointedDripstoneBlockAccessor.callFindRootBlock(level, pos, state, 11).map(blockPos -> {
BlockPos position = blockPos.above();
BlockState sourceState = level.getBlockState(position);
Fluid fluid = sourceState.is(WBBlockTags.MUD) && !level.dimensionType().ultraWarm() ? Fluids.WATER : level.getFluidState(position).getType();
return new DrippingFluid(position, fluid, sourceState);
});
public static Optional<DrippingFluid> getFluidAboveStalactite(
Level level, BlockPos pos, BlockState state
) {
return !PointedDripstoneBlockAccessor.callIsStalactite(state)
? Optional.empty()
: PointedDripstoneBlockAccessor.callFindRootBlock(level, pos, state, 11)
.map(blockPos -> {
BlockPos position = blockPos.above();
BlockState sourceState = level.getBlockState(position);
Fluid fluid = sourceState.is(WBBlockTags.MUD)
&& !level.dimensionType().ultraWarm()
? Fluids.WATER
: level.getFluidState(position).getType();
return new DrippingFluid(position, fluid, sourceState);
});
}
}

View file

@ -1,5 +1,7 @@
package com.cursedcauldron.wildbackport.common.blocks;
import java.util.Random;
import com.cursedcauldron.wildbackport.client.registry.WBSoundEvents;
import com.cursedcauldron.wildbackport.common.entities.Tadpole;
import com.cursedcauldron.wildbackport.common.registry.entity.WBEntityTypes;
@ -22,19 +24,20 @@ import net.minecraft.world.level.material.Fluids;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
import java.util.Random;
//<>
public class FrogspawnBlock extends Block {
protected static final VoxelShape SHAPE = Block.box(0.0D, 0.0D, 0.0D, 16.0D, 1.5D, 16.0D);
protected static final VoxelShape SHAPE
= Block.box(0.0D, 0.0D, 0.0D, 16.0D, 1.5D, 16.0D);
public FrogspawnBlock(Properties properties) {
super(properties);
}
@Override
public VoxelShape getShape(BlockState state, BlockGetter getter, BlockPos pos, CollisionContext context) {
public VoxelShape getShape(
BlockState state, BlockGetter getter, BlockPos pos, CollisionContext context
) {
return SHAPE;
}
@ -44,7 +47,9 @@ public class FrogspawnBlock extends Block {
}
@Override
public void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean notify) {
public void onPlace(
BlockState state, Level level, BlockPos pos, BlockState oldState, boolean notify
) {
level.scheduleTick(pos, this, hatchTime(level.getRandom()));
}
@ -53,8 +58,19 @@ public class FrogspawnBlock extends Block {
}
@Override
public BlockState updateShape(BlockState state, Direction direction, BlockState neighborState, LevelAccessor access, BlockPos pos, BlockPos neighborPos) {
return !this.canSurvive(state, access, pos) ? Blocks.AIR.defaultBlockState() : super.updateShape(state, direction, neighborState, access, pos, neighborPos);
public BlockState updateShape(
BlockState state,
Direction direction,
BlockState neighborState,
LevelAccessor access,
BlockPos pos,
BlockPos neighborPos
) {
return !this.canSurvive(state, access, pos)
? Blocks.AIR.defaultBlockState()
: super.updateShape(
state, direction, neighborState, access, pos, neighborPos
);
}
@Override
@ -76,12 +92,15 @@ public class FrogspawnBlock extends Block {
private static boolean mayPlaceOn(LevelReader reader, BlockPos pos) {
FluidState fluidState = reader.getFluidState(pos);
FluidState topFluidState = reader.getFluidState(pos.above());
return fluidState.getType() == Fluids.WATER && topFluidState.getType() == Fluids.EMPTY;
return fluidState.getType() == Fluids.WATER
&& topFluidState.getType() == Fluids.EMPTY;
}
private void onHatch(ServerLevel level, BlockPos pos, Random random) {
this.hatch(level, pos);
level.playSound(null, pos, WBSoundEvents.BLOCK_FROGSPAWN_HATCH, SoundSource.BLOCKS, 1.0F, 1.0F);
level.playSound(
null, pos, WBSoundEvents.BLOCK_FROGSPAWN_HATCH, SoundSource.BLOCKS, 1.0F, 1.0F
);
this.createTadpole(level, pos, random);
}
@ -95,10 +114,10 @@ public class FrogspawnBlock extends Block {
for (int index = 1; index <= i; ++index) {
Tadpole tadpole = WBEntityTypes.TADPOLE.get().create(level);
if (tadpole != null) {
double x = (double)pos.getX() + this.getSpawnOffset(random);
double z = (double)pos.getZ() + this.getSpawnOffset(random);
double x = (double) pos.getX() + this.getSpawnOffset(random);
double z = (double) pos.getZ() + this.getSpawnOffset(random);
int yaw = random.nextInt(1, 361);
tadpole.moveTo(x, (double)pos.getY() - 0.5, z, yaw, 0.0F);
tadpole.moveTo(x, (double) pos.getY() - 0.5, z, yaw, 0.0F);
tadpole.setPersistenceRequired();
level.addFreshEntity(tadpole);
}

View file

@ -1,5 +1,7 @@
package com.cursedcauldron.wildbackport.common.blocks;
import java.util.Random;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.BlockGetter;
@ -8,8 +10,6 @@ import net.minecraft.world.level.block.BonemealableBlock;
import net.minecraft.world.level.block.LeavesBlock;
import net.minecraft.world.level.block.state.BlockState;
import java.util.Random;
//<>
public class MangroveLeavesBlock extends LeavesBlock implements BonemealableBlock {
@ -18,17 +18,21 @@ public class MangroveLeavesBlock extends LeavesBlock implements BonemealableBloc
}
@Override
public boolean isValidBonemealTarget(BlockGetter block, BlockPos pos, BlockState state, boolean flag) {
public boolean isValidBonemealTarget(
BlockGetter block, BlockPos pos, BlockState state, boolean flag
) {
return block.getBlockState(pos.below()).isAir();
}
@Override
public boolean isBonemealSuccess(Level level, Random random, BlockPos pos, BlockState state) {
public boolean
isBonemealSuccess(Level level, Random random, BlockPos pos, BlockState state) {
return true;
}
@Override
public void performBonemeal(ServerLevel level, Random random, BlockPos pos, BlockState state) {
public void
performBonemeal(ServerLevel level, Random random, BlockPos pos, BlockState state) {
level.setBlock(pos.below(), MangrovePropaguleBlock.createPropagule(), 2);
}
}

View file

@ -1,5 +1,7 @@
package com.cursedcauldron.wildbackport.common.blocks;
import java.util.Random;
import com.cursedcauldron.wildbackport.common.registry.WBBlocks;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
@ -25,23 +27,32 @@ import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
import org.jetbrains.annotations.Nullable;
import java.util.Random;
//<>
public class MangrovePropaguleBlock extends SaplingBlock implements SimpleWaterloggedBlock {
private static final VoxelShape[] SHAPES = new VoxelShape[]{Block.box(7.0D, 13.0D, 7.0D, 9.0D, 16.0D, 9.0D), Block.box(7.0D, 10.0D, 7.0D, 9.0D, 16.0D, 9.0D), Block.box(7.0D, 7.0D, 7.0D, 9.0D, 16.0D, 9.0D), Block.box(7.0D, 3.0D, 7.0D, 9.0D, 16.0D, 9.0D), Block.box(7.0D, 0.0D, 7.0D, 9.0D, 16.0D, 9.0D)};
public class MangrovePropaguleBlock
extends SaplingBlock implements SimpleWaterloggedBlock {
private static final VoxelShape[] SHAPES
= new VoxelShape[] { Block.box(7.0D, 13.0D, 7.0D, 9.0D, 16.0D, 9.0D),
Block.box(7.0D, 10.0D, 7.0D, 9.0D, 16.0D, 9.0D),
Block.box(7.0D, 7.0D, 7.0D, 9.0D, 16.0D, 9.0D),
Block.box(7.0D, 3.0D, 7.0D, 9.0D, 16.0D, 9.0D),
Block.box(7.0D, 0.0D, 7.0D, 9.0D, 16.0D, 9.0D) };
public static final IntegerProperty AGE = StateProperties.AGE_4;
public static final BooleanProperty WATERLOGGED = BlockStateProperties.WATERLOGGED;
public static final BooleanProperty HANGING = BlockStateProperties.HANGING;
public MangrovePropaguleBlock(Properties properties) {
super(new MangroveTreeGrower(0.85F), properties);
this.registerDefaultState(this.stateDefinition.any().setValue(STAGE, 0).setValue(AGE, 0).setValue(WATERLOGGED, false).setValue(HANGING, false));
this.registerDefaultState(this.stateDefinition.any()
.setValue(STAGE, 0)
.setValue(AGE, 0)
.setValue(WATERLOGGED, false)
.setValue(HANGING, false));
}
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
protected void
createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
builder.add(STAGE, AGE, WATERLOGGED, HANGING);
}
@ -50,28 +61,47 @@ public class MangrovePropaguleBlock extends SaplingBlock implements SimpleWaterl
return super.mayPlaceOn(state, block, pos) || state.is(Blocks.CLAY);
}
@Override @Nullable @SuppressWarnings("ConstantConditions")
@Override
@Nullable
@SuppressWarnings("ConstantConditions")
public BlockState getStateForPlacement(BlockPlaceContext ctx) {
FluidState fluidState = ctx.getLevel().getFluidState(ctx.getClickedPos());
return super.getStateForPlacement(ctx).setValue(WATERLOGGED, fluidState.getType() == Fluids.WATER).setValue(AGE, 4);
return super.getStateForPlacement(ctx)
.setValue(WATERLOGGED, fluidState.getType() == Fluids.WATER)
.setValue(AGE, 4);
}
@Override
public VoxelShape getShape(BlockState state, BlockGetter block, BlockPos pos, CollisionContext context) {
public VoxelShape getShape(
BlockState state, BlockGetter block, BlockPos pos, CollisionContext context
) {
Vec3 offset = state.getOffset(block, pos);
VoxelShape shape = !state.getValue(HANGING) ? SHAPES[4] : SHAPES[state.getValue(AGE)];
VoxelShape shape
= !state.getValue(HANGING) ? SHAPES[4] : SHAPES[state.getValue(AGE)];
return shape.move(offset.x, offset.y, offset.z);
}
@Override
public boolean canSurvive(BlockState state, LevelReader level, BlockPos pos) {
return isHanging(state) ? level.getBlockState(pos.above()).is(WBBlocks.MANGROVE_LEAVES.get()) : super.canSurvive(state, level, pos);
return isHanging(state)
? level.getBlockState(pos.above()).is(WBBlocks.MANGROVE_LEAVES.get())
: super.canSurvive(state, level, pos);
}
@Override
public BlockState updateShape(BlockState state, Direction direction, BlockState newState, LevelAccessor level, BlockPos pos, BlockPos newPos) {
if (state.getValue(WATERLOGGED)) level.scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickDelay(level));
return direction == Direction.UP && !state.canSurvive(level, pos) ? Blocks.AIR.defaultBlockState() : super.updateShape(state, direction, newState, level, pos, newPos);
public BlockState updateShape(
BlockState state,
Direction direction,
BlockState newState,
LevelAccessor level,
BlockPos pos,
BlockPos newPos
) {
if (state.getValue(WATERLOGGED))
level.scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickDelay(level));
return direction == Direction.UP && !state.canSurvive(level, pos)
? Blocks.AIR.defaultBlockState()
: super.updateShape(state, direction, newState, level, pos, newPos);
}
@Override
@ -81,30 +111,39 @@ public class MangrovePropaguleBlock extends SaplingBlock implements SimpleWaterl
@Override
public FluidState getFluidState(BlockState state) {
return state.getValue(WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(state);
return state.getValue(WATERLOGGED) ? Fluids.WATER.getSource(false)
: super.getFluidState(state);
}
@Override
public void randomTick(BlockState state, ServerLevel level, BlockPos pos, Random random) {
public void
randomTick(BlockState state, ServerLevel level, BlockPos pos, Random random) {
if (!isHanging(state)) {
if (random.nextInt(7) == 0) this.advanceTree(level, pos, state, random);
if (random.nextInt(7) == 0)
this.advanceTree(level, pos, state, random);
} else {
if (!ageAtMax(state)) level.setBlock(pos, state.cycle(AGE), 2);
if (!ageAtMax(state))
level.setBlock(pos, state.cycle(AGE), 2);
}
}
@Override
public boolean isValidBonemealTarget(BlockGetter block, BlockPos pos, BlockState state, boolean flag) {
public boolean isValidBonemealTarget(
BlockGetter block, BlockPos pos, BlockState state, boolean flag
) {
return !isHanging(state) || !ageAtMax(state);
}
@Override
public boolean isBonemealSuccess(Level level, Random random, BlockPos pos, BlockState state) {
return isHanging(state) ? !ageAtMax(state) : super.isBonemealSuccess(level, random, pos, state);
public boolean
isBonemealSuccess(Level level, Random random, BlockPos pos, BlockState state) {
return isHanging(state) ? !ageAtMax(state)
: super.isBonemealSuccess(level, random, pos, state);
}
@Override
public void performBonemeal(ServerLevel level, Random random, BlockPos pos, BlockState state) {
public void
performBonemeal(ServerLevel level, Random random, BlockPos pos, BlockState state) {
if (isHanging(state) && !ageAtMax(state)) {
level.setBlock(pos, state.cycle(AGE), 2);
} else {
@ -125,6 +164,9 @@ public class MangrovePropaguleBlock extends SaplingBlock implements SimpleWaterl
}
public static BlockState createPropagule(int age) {
return WBBlocks.MANGROVE_PROPAGULE.get().defaultBlockState().setValue(HANGING, true).setValue(AGE, age);
return WBBlocks.MANGROVE_PROPAGULE.get()
.defaultBlockState()
.setValue(HANGING, true)
.setValue(AGE, age);
}
}

View file

@ -21,32 +21,50 @@ public class MangroveRootsBlock extends Block implements SimpleWaterloggedBlock
public MangroveRootsBlock(BlockBehaviour.Properties properties) {
super(properties);
this.registerDefaultState(this.stateDefinition.any().setValue(WATERLOGGED, false));
this.registerDefaultState(this.stateDefinition.any().setValue(WATERLOGGED, false)
);
}
@Override
public boolean skipRendering(BlockState state, BlockState stateFrom, Direction direction) {
return stateFrom.is(WBBlocks.MANGROVE_ROOTS.get()) && direction.getAxis() == Direction.Axis.Y;
public boolean
skipRendering(BlockState state, BlockState stateFrom, Direction direction) {
return stateFrom.is(WBBlocks.MANGROVE_ROOTS.get())
&& direction.getAxis() == Direction.Axis.Y;
}
@Override @Nullable @SuppressWarnings("ConstantConditions")
@Override
@Nullable
@SuppressWarnings("ConstantConditions")
public BlockState getStateForPlacement(BlockPlaceContext ctx) {
return super.getStateForPlacement(ctx).setValue(WATERLOGGED, ctx.getLevel().getFluidState(ctx.getClickedPos()).getType() == Fluids.WATER);
return super.getStateForPlacement(ctx).setValue(
WATERLOGGED,
ctx.getLevel().getFluidState(ctx.getClickedPos()).getType() == Fluids.WATER
);
}
@Override
public BlockState updateShape(BlockState state, Direction direction, BlockState newState, LevelAccessor level, BlockPos pos, BlockPos newPos) {
if (state.getValue(WATERLOGGED)) level.scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickDelay(level));
public BlockState updateShape(
BlockState state,
Direction direction,
BlockState newState,
LevelAccessor level,
BlockPos pos,
BlockPos newPos
) {
if (state.getValue(WATERLOGGED))
level.scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickDelay(level));
return super.updateShape(state, direction, newState, level, pos, newPos);
}
@Override
public FluidState getFluidState(BlockState state) {
return state.getValue(WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(state);
return state.getValue(WATERLOGGED) ? Fluids.WATER.getSource(false)
: super.getFluidState(state);
}
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
protected void
createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
builder.add(WATERLOGGED);
}
}

View file

@ -1,13 +1,13 @@
package com.cursedcauldron.wildbackport.common.blocks;
import java.util.Random;
import com.cursedcauldron.wildbackport.common.registry.worldgen.WBWorldGeneration;
import net.minecraft.core.Holder;
import net.minecraft.world.level.block.grower.AbstractTreeGrower;
import net.minecraft.world.level.levelgen.feature.ConfiguredFeature;
import org.jetbrains.annotations.Nullable;
import java.util.Random;
public class MangroveTreeGrower extends AbstractTreeGrower {
private final float tallChance;
@ -15,8 +15,11 @@ public class MangroveTreeGrower extends AbstractTreeGrower {
this.tallChance = tallChance;
}
@Override @Nullable
protected Holder<? extends ConfiguredFeature<?, ?>> getConfiguredFeature(Random random, boolean bees) {
return random.nextFloat() < this.tallChance ? WBWorldGeneration.TALL_MANGROVE : WBWorldGeneration.MANGROVE;
@Override
@Nullable
protected Holder<? extends ConfiguredFeature<?, ?>>
getConfiguredFeature(Random random, boolean bees) {
return random.nextFloat() < this.tallChance ? WBWorldGeneration.TALL_MANGROVE
: WBWorldGeneration.MANGROVE;
}
}

View file

@ -10,29 +10,40 @@ import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.VoxelShape;
public class MudBlock extends Block {
private static final VoxelShape SHAPE = Block.box(0.0D, 0.0D, 0.0D, 16.0D, 14.0D, 16.0D);
private static final VoxelShape SHAPE
= Block.box(0.0D, 0.0D, 0.0D, 16.0D, 14.0D, 16.0D);
public MudBlock(Properties properties) {
super(properties);
}
@Override
public VoxelShape getBlockSupportShape(BlockState state, BlockGetter getter, BlockPos pos) {
public VoxelShape
getBlockSupportShape(BlockState state, BlockGetter getter, BlockPos pos) {
return Shapes.block();
}
@Override
public VoxelShape getVisualShape(BlockState state, BlockGetter getter, BlockPos pos, CollisionContext context) {
public VoxelShape getVisualShape(
BlockState state, BlockGetter getter, BlockPos pos, CollisionContext context
) {
return Shapes.block();
}
@Override
public VoxelShape getCollisionShape(BlockState state, BlockGetter getter, BlockPos pos, CollisionContext context) {
public VoxelShape getCollisionShape(
BlockState state, BlockGetter getter, BlockPos pos, CollisionContext context
) {
return SHAPE;
}
@Override
public boolean isPathfindable(BlockState state, BlockGetter getter, BlockPos pos, PathComputationType pathComputation) {
public boolean isPathfindable(
BlockState state,
BlockGetter getter,
BlockPos pos,
PathComputationType pathComputation
) {
return false;
}

View file

@ -1,5 +1,7 @@
package com.cursedcauldron.wildbackport.common.blocks;
import java.util.Random;
import com.cursedcauldron.wildbackport.common.registry.WBBlocks;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
@ -15,15 +17,20 @@ import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.material.Fluids;
import java.util.Random;
public class SculkBlock extends OreBlock implements SculkSpreadable {
public SculkBlock(Properties properties) {
super(properties);
}
@Override
public int spread(SculkSpreadManager.Cursor cursor, LevelAccessor level, BlockPos pos, Random random, SculkSpreadManager manager, boolean shouldConvert) {
public int spread(
SculkSpreadManager.Cursor cursor,
LevelAccessor level,
BlockPos pos,
Random random,
SculkSpreadManager manager,
boolean shouldConvert
) {
int charge = cursor.getCharge();
if (charge != 0 && random.nextInt(manager.getSpreadChance()) == 0) {
BlockPos blockPos = cursor.getPos();
@ -32,41 +39,66 @@ public class SculkBlock extends OreBlock implements SculkSpreadable {
int chance = manager.getExtraBlockChance();
if (random.nextInt(chance) < charge) {
BlockPos growthPos = blockPos.above();
BlockState state = this.getExtraBlockState(level, growthPos, random, manager.isWorldGen());
BlockState state = this.getExtraBlockState(
level, growthPos, random, manager.isWorldGen()
);
level.setBlock(growthPos, state, 3);
level.playSound(null, blockPos, state.getSoundType().getPlaceSound(), SoundSource.BLOCKS, 1.0F, 1.0F);
level.playSound(
null,
blockPos,
state.getSoundType().getPlaceSound(),
SoundSource.BLOCKS,
1.0F,
1.0F
);
}
return Math.max(0, charge - chance);
} else {
return random.nextInt(manager.getDecayChance()) != 0 ? charge : charge - (inRange ? 1 : getDecay(manager, blockPos, pos, charge));
return random.nextInt(manager.getDecayChance()) != 0
? charge
: charge - (inRange ? 1 : getDecay(manager, blockPos, pos, charge));
}
} else {
return charge;
}
}
private static int getDecay(SculkSpreadManager manager, BlockPos source, BlockPos target, int charge) {
private static int
getDecay(SculkSpreadManager manager, BlockPos source, BlockPos target, int charge) {
int maxDistance = manager.getMaxDistance();
float range = Mth.square((float)Math.sqrt(source.distSqr(target)) - (float)maxDistance);
float range
= Mth.square((float) Math.sqrt(source.distSqr(target)) - (float) maxDistance);
int distance = Mth.square(24 - maxDistance);
float spread = Math.min(1.0F, range / (float)distance);
return Math.max(1, (int)((float)charge * spread * 0.5F));
float spread = Math.min(1.0F, range / (float) distance);
return Math.max(1, (int) ((float) charge * spread * 0.5F));
}
private BlockState getExtraBlockState(LevelAccessor level, BlockPos pos, Random random, boolean isWorldGen) {
BlockState state = random.nextInt(11) == 0 ? WBBlocks.SCULK_SHRIEKER.get().defaultBlockState().setValue(SculkShriekerBlock.CAN_SUMMON, isWorldGen) : Blocks.SCULK_SENSOR.defaultBlockState();
return state.hasProperty(BlockStateProperties.WATERLOGGED) && !level.getFluidState(pos).isEmpty() ? state.setValue(BlockStateProperties.WATERLOGGED, true) : state;
private BlockState getExtraBlockState(
LevelAccessor level, BlockPos pos, Random random, boolean isWorldGen
) {
BlockState state = random.nextInt(11) == 0
? WBBlocks.SCULK_SHRIEKER.get().defaultBlockState().setValue(
SculkShriekerBlock.CAN_SUMMON, isWorldGen
)
: Blocks.SCULK_SENSOR.defaultBlockState();
return state.hasProperty(BlockStateProperties.WATERLOGGED)
&& !level.getFluidState(pos).isEmpty()
? state.setValue(BlockStateProperties.WATERLOGGED, true)
: state;
}
private static boolean shouldNotDecay(LevelAccessor level, BlockPos pos) {
BlockState state = level.getBlockState(pos.above());
if (state.isAir() || state.is(Blocks.WATER) && state.getFluidState().is(Fluids.WATER)) {
if (state.isAir()
|| state.is(Blocks.WATER) && state.getFluidState().is(Fluids.WATER)) {
int chance = 0;
for (BlockPos position : BlockPos.betweenClosed(pos.offset(-4, 0, -4), pos.offset(4, 2, 4))) {
for (BlockPos position :
BlockPos.betweenClosed(pos.offset(-4, 0, -4), pos.offset(4, 2, 4))) {
BlockState growth = level.getBlockState(position);
if (growth.is(Blocks.SCULK_SENSOR) || growth.is(WBBlocks.SCULK_SHRIEKER.get())) {
if (growth.is(Blocks.SCULK_SENSOR)
|| growth.is(WBBlocks.SCULK_SHRIEKER.get())) {
++chance;
}
@ -82,8 +114,11 @@ public class SculkBlock extends OreBlock implements SculkSpreadable {
}
@Override
public void spawnAfterBreak(BlockState state, ServerLevel level, BlockPos pos, ItemStack stack) {
if (EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, stack) == 0) this.popExperience(level, pos, 1);
public void
spawnAfterBreak(BlockState state, ServerLevel level, BlockPos pos, ItemStack stack) {
if (EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, stack)
== 0)
this.popExperience(level, pos, 1);
}
@Override

View file

@ -1,5 +1,7 @@
package com.cursedcauldron.wildbackport.common.blocks;
import java.util.Random;
import com.cursedcauldron.wildbackport.client.registry.WBParticleTypes;
import com.cursedcauldron.wildbackport.client.registry.WBSoundEvents;
import com.cursedcauldron.wildbackport.common.blocks.entity.SculkCatalystBlockEntity;
@ -23,8 +25,6 @@ import net.minecraft.world.level.block.state.properties.BooleanProperty;
import net.minecraft.world.level.gameevent.GameEventListener;
import org.jetbrains.annotations.Nullable;
import java.util.Random;
//<>
public class SculkCatalystBlock extends BaseEntityBlock {
@ -36,35 +36,63 @@ public class SculkCatalystBlock extends BaseEntityBlock {
}
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
protected void
createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
builder.add(BLOOM);
}
@Override
public void tick(BlockState state, ServerLevel level, BlockPos pos, Random random) {
if (state.getValue(BLOOM)) level.setBlock(pos, state.setValue(BLOOM, false), 3);
if (state.getValue(BLOOM))
level.setBlock(pos, state.setValue(BLOOM, false), 3);
}
public static void bloom(ServerLevel level, BlockPos pos, BlockState state, Random random) {
public static void
bloom(ServerLevel level, BlockPos pos, BlockState state, Random random) {
level.setBlock(pos, state.setValue(BLOOM, true), 3);
level.scheduleTick(pos, state.getBlock(), 8);
level.sendParticles(WBParticleTypes.SCULK_SOUL.get(), (double)pos.getX() + 0.5D, (double)pos.getY() + 1.15D, (double)pos.getZ() + 0.5D, 2, 0.2D, 0.0D, 0.2D, 0.0D);
level.playSound(null, pos, WBSoundEvents.BLOCK_SCULK_CATALYST_BLOOM, SoundSource.BLOCKS, 2.0F, 0.6F + random.nextFloat() * 0.4F);
level.sendParticles(
WBParticleTypes.SCULK_SOUL.get(),
(double) pos.getX() + 0.5D,
(double) pos.getY() + 1.15D,
(double) pos.getZ() + 0.5D,
2,
0.2D,
0.0D,
0.2D,
0.0D
);
level.playSound(
null,
pos,
WBSoundEvents.BLOCK_SCULK_CATALYST_BLOOM,
SoundSource.BLOCKS,
2.0F,
0.6F + random.nextFloat() * 0.4F
);
}
@Nullable @Override
@Nullable
@Override
public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {
return new SculkCatalystBlockEntity(pos, state);
}
@Nullable @Override
@Nullable
@Override
public <T extends BlockEntity> GameEventListener getListener(Level level, T type) {
return type instanceof SculkCatalystBlockEntity catalyst ? catalyst : null;
}
@Nullable @Override
public <T extends BlockEntity> BlockEntityTicker<T> getTicker(Level level, BlockState state, BlockEntityType<T> type) {
return level.isClientSide ? null : createTickerHelper(type, WBBlockEntities.SCULK_CATALYST.get(), SculkCatalystBlockEntity::tick);
@Nullable
@Override
public <T extends BlockEntity> BlockEntityTicker<T>
getTicker(Level level, BlockState state, BlockEntityType<T> type) {
return level.isClientSide
? null
: createTickerHelper(
type, WBBlockEntities.SCULK_CATALYST.get(), SculkCatalystBlockEntity::tick
);
}
@Override
@ -73,7 +101,10 @@ public class SculkCatalystBlock extends BaseEntityBlock {
}
@Override
public void spawnAfterBreak(BlockState state, ServerLevel level, BlockPos pos, ItemStack stack) {
if (EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, stack) == 0) this.popExperience(level, pos, 5);
public void
spawnAfterBreak(BlockState state, ServerLevel level, BlockPos pos, ItemStack stack) {
if (EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, stack)
== 0)
this.popExperience(level, pos, 5);
}
}

View file

@ -1,5 +1,7 @@
package com.cursedcauldron.wildbackport.common.blocks;
import java.util.Random;
import com.cursedcauldron.wildbackport.common.blocks.entity.SculkShriekerBlockEntity;
import com.cursedcauldron.wildbackport.common.registry.WBBlockEntities;
import net.minecraft.core.BlockPos;
@ -32,24 +34,28 @@ import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
import org.jetbrains.annotations.Nullable;
import java.util.Random;
//<>
public class SculkShriekerBlock extends BaseEntityBlock implements SimpleWaterloggedBlock {
public class SculkShriekerBlock
extends BaseEntityBlock implements SimpleWaterloggedBlock {
public static final BooleanProperty SHRIEKING = StateProperties.SHRIEKING;
public static final BooleanProperty CAN_SUMMON = StateProperties.CAN_SUMMON;
public static final BooleanProperty WATERLOGGED = BlockStateProperties.WATERLOGGED;
private static final VoxelShape SHAPE = Block.box(0.0D, 0.0D, 0.0D, 16.0D, 8.0D, 16.0D);
private static final VoxelShape SHAPE
= Block.box(0.0D, 0.0D, 0.0D, 16.0D, 8.0D, 16.0D);
public static final double TOP_Y = SHAPE.max(Direction.Axis.Y);
public SculkShriekerBlock(Properties properties) {
super(properties);
this.registerDefaultState(this.stateDefinition.any().setValue(SHRIEKING, false).setValue(WATERLOGGED, false).setValue(CAN_SUMMON, false));
this.registerDefaultState(this.stateDefinition.any()
.setValue(SHRIEKING, false)
.setValue(WATERLOGGED, false)
.setValue(CAN_SUMMON, false));
}
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
protected void
createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
builder.add(SHRIEKING, WATERLOGGED, CAN_SUMMON);
}
@ -58,7 +64,8 @@ public class SculkShriekerBlock extends BaseEntityBlock implements SimpleWaterlo
if (level instanceof ServerLevel server) {
ServerPlayer player = SculkShriekerBlockEntity.tryGetPlayer(entity);
if (player != null) {
server.getBlockEntity(pos, WBBlockEntities.SCULK_SHRIEKER.get()).ifPresent(shrieker -> shrieker.tryShriek(server, player));
server.getBlockEntity(pos, WBBlockEntities.SCULK_SHRIEKER.get())
.ifPresent(shrieker -> shrieker.tryShriek(server, player));
}
}
@ -66,10 +73,13 @@ public class SculkShriekerBlock extends BaseEntityBlock implements SimpleWaterlo
}
@Override
public void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean moving) {
public void onRemove(
BlockState state, Level level, BlockPos pos, BlockState newState, boolean moving
) {
if (level instanceof ServerLevel server) {
if (state.getValue(SHRIEKING) && !state.is(newState.getBlock())) {
server.getBlockEntity(pos, WBBlockEntities.SCULK_SHRIEKER.get()).ifPresent(shrieker -> shrieker.tryRespond(server));
server.getBlockEntity(pos, WBBlockEntities.SCULK_SHRIEKER.get())
.ifPresent(shrieker -> shrieker.tryRespond(server));
}
}
@ -80,7 +90,8 @@ public class SculkShriekerBlock extends BaseEntityBlock implements SimpleWaterlo
public void tick(BlockState state, ServerLevel level, BlockPos pos, Random random) {
if (state.getValue(SHRIEKING)) {
level.setBlock(pos, state.setValue(SHRIEKING, false), 3);
level.getBlockEntity(pos, WBBlockEntities.SCULK_SHRIEKER.get()).ifPresent(shrieker -> shrieker.tryRespond(level));
level.getBlockEntity(pos, WBBlockEntities.SCULK_SHRIEKER.get())
.ifPresent(shrieker -> shrieker.tryRespond(level));
}
}
@ -90,12 +101,15 @@ public class SculkShriekerBlock extends BaseEntityBlock implements SimpleWaterlo
}
@Override
public VoxelShape getCollisionShape(BlockState state, BlockGetter getter, BlockPos pos, CollisionContext context) {
public VoxelShape getCollisionShape(
BlockState state, BlockGetter getter, BlockPos pos, CollisionContext context
) {
return SHAPE;
}
@Override
public VoxelShape getOcclusionShape(BlockState state, BlockGetter getter, BlockPos pos) {
public VoxelShape
getOcclusionShape(BlockState state, BlockGetter getter, BlockPos pos) {
return SHAPE;
}
@ -104,39 +118,67 @@ public class SculkShriekerBlock extends BaseEntityBlock implements SimpleWaterlo
return true;
}
@Nullable @Override
@Nullable
@Override
public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {
return new SculkShriekerBlockEntity(pos, state);
}
@Override
public BlockState updateShape(BlockState state, Direction direction, BlockState newState, LevelAccessor level, BlockPos pos, BlockPos newPos) {
if (state.getValue(WATERLOGGED)) level.scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickDelay(level));
public BlockState updateShape(
BlockState state,
Direction direction,
BlockState newState,
LevelAccessor level,
BlockPos pos,
BlockPos newPos
) {
if (state.getValue(WATERLOGGED))
level.scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickDelay(level));
return super.updateShape(state, direction, newState, level, pos, newPos);
}
@Nullable @Override
@Nullable
@Override
public BlockState getStateForPlacement(BlockPlaceContext context) {
return this.defaultBlockState().setValue(WATERLOGGED, context.getLevel().getFluidState(context.getClickedPos()).getType() == Fluids.WATER);
return this.defaultBlockState().setValue(
WATERLOGGED,
context.getLevel().getFluidState(context.getClickedPos()).getType()
== Fluids.WATER
);
}
@Override
public FluidState getFluidState(BlockState state) {
return state.getValue(WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(state);
return state.getValue(WATERLOGGED) ? Fluids.WATER.getSource(false)
: super.getFluidState(state);
}
@Override
public void spawnAfterBreak(BlockState state, ServerLevel level, BlockPos pos, ItemStack stack) {
if (EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, stack) == 0) this.popExperience(level, pos, 5);
public void
spawnAfterBreak(BlockState state, ServerLevel level, BlockPos pos, ItemStack stack) {
if (EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, stack)
== 0)
this.popExperience(level, pos, 5);
}
@Nullable @Override
@Nullable
@Override
public <T extends BlockEntity> GameEventListener getListener(Level level, T type) {
return type instanceof SculkShriekerBlockEntity shrieker ? shrieker.getListener() : null;
return type instanceof SculkShriekerBlockEntity shrieker ? shrieker.getListener()
: null;
}
@Nullable @Override
public <T extends BlockEntity> BlockEntityTicker<T> getTicker(Level level, BlockState state, BlockEntityType<T> type) {
return !level.isClientSide ? createTickerHelper(type, WBBlockEntities.SCULK_SHRIEKER.get(), (levelIn, posIn, stateIn, shrieker) -> shrieker.getListener().tick(levelIn)) : null;
@Nullable
@Override
public <T extends BlockEntity> BlockEntityTicker<T>
getTicker(Level level, BlockState state, BlockEntityType<T> type) {
return !level.isClientSide ? createTickerHelper(
type,
WBBlockEntities.SCULK_SHRIEKER.get(),
(levelIn, posIn, stateIn, shrieker
) -> shrieker.getListener().tick(levelIn)
)
: null;
}
}

View file

@ -1,5 +1,14 @@
package com.cursedcauldron.wildbackport.common.blocks;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Random;
import java.util.Set;
import java.util.function.Supplier;
import com.cursedcauldron.wildbackport.WildBackport;
import com.cursedcauldron.wildbackport.client.particle.SculkChargeParticleOptions;
import com.cursedcauldron.wildbackport.client.registry.WBParticleTypes;
@ -36,15 +45,6 @@ import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.Vec3;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Random;
import java.util.Set;
import java.util.function.Supplier;
public class SculkSpreadManager {
final boolean isWorldGen;
private final TagKey<Block> replaceableBlocks;
@ -54,7 +54,14 @@ public class SculkSpreadManager {
private final int decayChance;
private List<Cursor> cursors = new ArrayList<>();
public SculkSpreadManager(boolean isWorldGen, TagKey<Block> replaceableBlocks, int extraBlockChance, int maxDistance, int spreadChance, int decayChance) {
public SculkSpreadManager(
boolean isWorldGen,
TagKey<Block> replaceableBlocks,
int extraBlockChance,
int maxDistance,
int spreadChance,
int decayChance
) {
this.isWorldGen = isWorldGen;
this.replaceableBlocks = replaceableBlocks;
this.extraBlockChance = extraBlockChance;
@ -68,7 +75,9 @@ public class SculkSpreadManager {
}
public static SculkSpreadManager createWorldGen() {
return new SculkSpreadManager(true, WBBlockTags.SCULK_REPLACEABLE_WORLD_GEN, 50, 1, 5, 10);
return new SculkSpreadManager(
true, WBBlockTags.SCULK_REPLACEABLE_WORLD_GEN, 50, 1, 5, 10
);
}
public TagKey<Block> getReplaceableBlocks() {
@ -102,7 +111,11 @@ public class SculkSpreadManager {
public void readTag(CompoundTag tag) {
if (tag.contains("cursors", 9)) {
this.cursors.clear();
List<Cursor> cursors = Cursor.CODEC.listOf().parse(new Dynamic<>(NbtOps.INSTANCE, tag.getList("cursors", 10))).resultOrPartial(WildBackport.LOGGER::error).orElseGet(ArrayList::new);
List<Cursor> cursors
= Cursor.CODEC.listOf()
.parse(new Dynamic<>(NbtOps.INSTANCE, tag.getList("cursors", 10)))
.resultOrPartial(WildBackport.LOGGER::error)
.orElseGet(ArrayList::new);
int size = Math.min(cursors.size(), 32);
for (int i = 0; i < size; i++) {
@ -112,9 +125,10 @@ public class SculkSpreadManager {
}
public void writeTag(CompoundTag tag) {
Cursor.CODEC.listOf().encodeStart(NbtOps.INSTANCE, this.cursors).resultOrPartial(WildBackport.LOGGER::error).ifPresent(value -> {
tag.put("cursors", value);
});
Cursor.CODEC.listOf()
.encodeStart(NbtOps.INSTANCE, this.cursors)
.resultOrPartial(WildBackport.LOGGER::error)
.ifPresent(value -> { tag.put("cursors", value); });
}
public void spread(BlockPos pos, int charge) {
@ -131,7 +145,8 @@ public class SculkSpreadManager {
}
}
public void tick(LevelAccessor level, BlockPos pos, Random random, boolean shouldConvert) {
public void
tick(LevelAccessor level, BlockPos pos, Random random, boolean shouldConvert) {
Level instance = level instanceof Level side ? side : null;
if (!this.cursors.isEmpty()) {
List<Cursor> cursors = new ArrayList<>();
@ -144,7 +159,11 @@ public class SculkSpreadManager {
applySculkCharge(instance, cursor.getPos(), 0);
} else {
BlockPos position = cursor.getPos();
positions.computeInt(position, (blockPos, charge) -> (charge == null ? 0 : charge) + cursor.charge);
positions.computeInt(
position,
(blockPos,
charge) -> (charge == null ? 0 : charge) + cursor.charge
);
Cursor target = cursorPositions.get(position);
if (target == null) {
cursorPositions.put(position, cursor);
@ -166,8 +185,9 @@ public class SculkSpreadManager {
Cursor cursor = cursorPositions.get(position);
Set<Direction> directions = cursor == null ? null : cursor.getFacings();
if (exp > 0 && directions != null) {
int charge = (int)(Math.log1p(exp) / (double)2.3F) + 1;
int data = (charge << 6) + SculkVeinBlock.directionsToFlag(directions);
int charge = (int) (Math.log1p(exp) / (double) 2.3F) + 1;
int data
= (charge << 6) + SculkVeinBlock.directionsToFlag(directions);
applySculkCharge(instance, cursor.getPos(), data);
}
}
@ -177,27 +197,60 @@ public class SculkSpreadManager {
}
public static class Cursor {
private static final ObjectArrayList<Vec3i> OFFSETS = Util.make(new ObjectArrayList<>(18), positions -> {
BlockPos.betweenClosedStream(new BlockPos(-1, -1, -1), new BlockPos(1, 1, 1)).filter(pos -> {
return (pos.getX() == 0 || pos.getY() == 0 || pos.getZ() == 0) && pos != BlockPos.ZERO;
}).map(BlockPos::immutable).forEach(positions::add);
});
private static final ObjectArrayList<Vec3i> OFFSETS
= Util.make(new ObjectArrayList<>(18), positions -> {
BlockPos
.betweenClosedStream(
new BlockPos(-1, -1, -1), new BlockPos(1, 1, 1)
)
.filter(pos -> {
return (pos.getX() == 0 || pos.getY() == 0 || pos.getZ() == 0)
&& pos != BlockPos.ZERO;
})
.map(BlockPos::immutable)
.forEach(positions::add);
});
private BlockPos pos;
private int charge;
private int updateDelay;
private int decayDelay;
@Nullable
private Set<Direction> facings;
private static final Codec<Set<Direction>> DIRECTION_SET = Direction.CODEC.listOf().xmap(directions -> Sets.newEnumSet(directions, Direction.class), Lists::newArrayList);
private static final Codec<Set<Direction>> DIRECTION_SET
= Direction.CODEC.listOf().xmap(
directions
-> Sets.newEnumSet(directions, Direction.class),
Lists::newArrayList
);
public static final Codec<Cursor> CODEC = RecordCodecBuilder.create(instance -> {
return instance.group(BlockPos.CODEC.fieldOf("pos").forGetter(Cursor::getPos), Codec.intRange(0, 1000).fieldOf("charge").orElse(0).forGetter(Cursor::getCharge), Codec.intRange(0, 1).fieldOf("decay_delay").orElse(1).forGetter(Cursor::getDecayDelay), Codec.intRange(0, Integer.MAX_VALUE).fieldOf("update_delay").orElse(0).forGetter(cursor -> {
return cursor.updateDelay;
}), DIRECTION_SET.optionalFieldOf("facings").forGetter(cursor -> {
return Optional.ofNullable(cursor.getFacings());
})).apply(instance, Cursor::new);
return instance
.group(
BlockPos.CODEC.fieldOf("pos").forGetter(Cursor::getPos),
Codec.intRange(0, 1000).fieldOf("charge").orElse(0).forGetter(
Cursor::getCharge
),
Codec.intRange(0, 1)
.fieldOf("decay_delay")
.orElse(1)
.forGetter(Cursor::getDecayDelay),
Codec.intRange(0, Integer.MAX_VALUE)
.fieldOf("update_delay")
.orElse(0)
.forGetter(cursor -> { return cursor.updateDelay; }),
DIRECTION_SET.optionalFieldOf("facings").forGetter(cursor -> {
return Optional.ofNullable(cursor.getFacings());
})
)
.apply(instance, Cursor::new);
});
private Cursor(BlockPos pos, int charge, int decayDelay, int updateDelay, Optional<Set<Direction>> facings) {
private Cursor(
BlockPos pos,
int charge,
int decayDelay,
int updateDelay,
Optional<Set<Direction>> facings
) {
this.pos = pos;
this.charge = charge;
this.decayDelay = decayDelay;
@ -238,31 +291,59 @@ public class SculkSpreadManager {
}
}
public void spread(LevelAccessor level, BlockPos pos, Random random, SculkSpreadManager spreadManager, boolean shouldConvert) {
public void spread(
LevelAccessor level,
BlockPos pos,
Random random,
SculkSpreadManager spreadManager,
boolean shouldConvert
) {
if (this.canSpread(level, pos, spreadManager.isWorldGen)) {
if (this.updateDelay > 0) {
--this.updateDelay;
} else {
BlockState state = level.getBlockState(this.pos);
SculkSpreadable spreadable = getSpreadable(state);
if (shouldConvert && spreadable.spread(level, this.pos, state, this.facings, spreadManager.isWorldGen())) {
if (shouldConvert
&& spreadable.spread(
level,
this.pos,
state,
this.facings,
spreadManager.isWorldGen()
)) {
if (spreadable.shouldConvertToSpreadable()) {
state = level.getBlockState(this.pos);
spreadable = getSpreadable(state);
}
level.playSound(null, this.pos, WBSoundEvents.BLOCK_SCULK_BREAK, SoundSource.BLOCKS, 1.0F, 1.0F);
level.playSound(
null,
this.pos,
WBSoundEvents.BLOCK_SCULK_BREAK,
SoundSource.BLOCKS,
1.0F,
1.0F
);
}
this.charge = spreadable.spread(this, level, pos, random, spreadManager, shouldConvert);
this.charge = spreadable.spread(
this, level, pos, random, spreadManager, shouldConvert
);
if (this.charge <= 0) {
spreadable.spreadAtSamePosition(level, state, this.pos, random);
} else {
BlockPos target = getSpreadPos(level, this.pos, random);
if (target != null) {
spreadable.spreadAtSamePosition(level, state, this.pos, random);
spreadable.spreadAtSamePosition(
level, state, this.pos, random
);
this.pos = target.immutable();
if (spreadManager.isWorldGen() && !this.pos.closerThan(new Vec3i(pos.getX(), this.pos.getY(), pos.getZ()), 15.0D)) {
if (spreadManager.isWorldGen()
&& !this.pos.closerThan(
new Vec3i(pos.getX(), this.pos.getY(), pos.getZ()),
15.0D
)) {
this.charge = 0;
return;
}
@ -288,7 +369,9 @@ public class SculkSpreadManager {
}
private static SculkSpreadable getSpreadable(BlockState state) {
return state.getBlock() instanceof SculkSpreadable spreadable ? spreadable : SculkSpreadable.DEFAULT;
return state.getBlock() instanceof SculkSpreadable spreadable
? spreadable
: SculkSpreadable.DEFAULT;
}
private static List<Vec3i> shuffleOffsets(Random random) {
@ -296,14 +379,16 @@ public class SculkSpreadManager {
}
@Nullable
private static BlockPos getSpreadPos(LevelAccessor level, BlockPos pos, Random random) {
private static BlockPos
getSpreadPos(LevelAccessor level, BlockPos pos, Random random) {
BlockPos.MutableBlockPos target = pos.mutable();
BlockPos.MutableBlockPos source = pos.mutable();
for (Vec3i offset : shuffleOffsets(random)) {
source.setWithOffset(pos, offset);
BlockState state = level.getBlockState(source);
if (state.getBlock() instanceof SculkSpreadable && canSpread(level, pos, source)) {
if (state.getBlock() instanceof SculkSpreadable
&& canSpread(level, pos, source)) {
target.set(source);
if (SculkVeinBlock.veinCoversSculkReplaceable(level, state, source)) {
break;
@ -314,66 +399,128 @@ public class SculkSpreadManager {
return target.equals(pos) ? null : target;
}
private static boolean canSpread(LevelAccessor level, BlockPos source, BlockPos target) {
private static boolean
canSpread(LevelAccessor level, BlockPos source, BlockPos target) {
if (source.distManhattan(target) == 1) {
return true;
} else {
BlockPos pos = target.subtract(target);
Direction xAxis = Direction.fromAxisAndDirection(Direction.Axis.X, pos.getX() < 0 ? Direction.AxisDirection.NEGATIVE : Direction.AxisDirection.POSITIVE);
Direction yAxis = Direction.fromAxisAndDirection(Direction.Axis.Y, pos.getY() < 0 ? Direction.AxisDirection.NEGATIVE : Direction.AxisDirection.POSITIVE);
Direction zAxis = Direction.fromAxisAndDirection(Direction.Axis.Z, pos.getZ() < 0 ? Direction.AxisDirection.NEGATIVE : Direction.AxisDirection.POSITIVE);
Direction xAxis = Direction.fromAxisAndDirection(
Direction.Axis.X,
pos.getX() < 0 ? Direction.AxisDirection.NEGATIVE
: Direction.AxisDirection.POSITIVE
);
Direction yAxis = Direction.fromAxisAndDirection(
Direction.Axis.Y,
pos.getY() < 0 ? Direction.AxisDirection.NEGATIVE
: Direction.AxisDirection.POSITIVE
);
Direction zAxis = Direction.fromAxisAndDirection(
Direction.Axis.Z,
pos.getZ() < 0 ? Direction.AxisDirection.NEGATIVE
: Direction.AxisDirection.POSITIVE
);
if (pos.getX() == 0) {
return canSpread(level, source, yAxis) || canSpread(level, source, zAxis);
return canSpread(level, source, yAxis)
|| canSpread(level, source, zAxis);
} else if (pos.getY() == 0) {
return canSpread(level, source, xAxis) || canSpread(level, source, zAxis);
return canSpread(level, source, xAxis)
|| canSpread(level, source, zAxis);
} else {
return canSpread(level, source, xAxis) || canSpread(level, source, yAxis);
return canSpread(level, source, xAxis)
|| canSpread(level, source, yAxis);
}
}
}
private static boolean canSpread(LevelAccessor level, BlockPos pos, Direction direction) {
private static boolean
canSpread(LevelAccessor level, BlockPos pos, Direction direction) {
BlockPos facing = pos.relative(direction);
return !level.getBlockState(facing).isFaceSturdy(level, facing, direction.getOpposite());
return !level.getBlockState(facing).isFaceSturdy(
level, facing, direction.getOpposite()
);
}
}
public static void applySculkCharge(Level level, BlockPos pos, int data) {
if (level == null) return;
if (level == null)
return;
Random random = level.getRandom();
ClientLevel client = level.isClientSide() && level instanceof ClientLevel side ? side : null;
ClientLevel client
= level.isClientSide() && level instanceof ClientLevel side ? side : null;
ServerLevel server = level instanceof ServerLevel side ? side : null;
int charge = data >> 6;
if (charge > 0) {
if (random.nextFloat() < (float)charge * 0.2F) {
float volume = 0.15F + 0.05F * (float)charge * (float)charge * random.nextFloat();
float pitch = 0.4F * (float)charge - 0.2F * random.nextFloat();
if (client != null) client.playLocalSound(pos, WBSoundEvents.BLOCK_SCULK_CHARGE, SoundSource.BLOCKS, volume, pitch, false);
if (random.nextFloat() < (float) charge * 0.2F) {
float volume = 0.15F
+ 0.05F * (float) charge * (float) charge * random.nextFloat();
float pitch = 0.4F * (float) charge - 0.2F * random.nextFloat();
if (client != null)
client.playLocalSound(
pos,
WBSoundEvents.BLOCK_SCULK_CHARGE,
SoundSource.BLOCKS,
volume,
pitch,
false
);
}
int facings = (byte)(data & 63);
int facings = (byte) (data & 63);
UniformInt spread = UniformInt.of(0, charge);
Supplier<Vec3> velocities = () -> {
return new Vec3(Mth.nextDouble(random, -0.005D, 0.005D), Mth.nextDouble(random, -0.005D, 0.005D), Mth.nextDouble(random, -0.005D, 0.005D));
return new Vec3(
Mth.nextDouble(random, -0.005D, 0.005D),
Mth.nextDouble(random, -0.005D, 0.005D),
Mth.nextDouble(random, -0.005D, 0.005D)
);
};
if (facings == 0) {
for (Direction direction : Direction.values()) {
float roll = direction == Direction.DOWN ? (float)Math.PI : 0.0F;
double offset = direction == Direction.UP || direction == Direction.DOWN ? 0.32D : 0.57D;
ParticleUtils.spawnParticles(level, pos, new SculkChargeParticleOptions(roll), spread, direction, velocities, offset);
float roll = direction == Direction.DOWN ? (float) Math.PI : 0.0F;
double offset
= direction == Direction.UP || direction == Direction.DOWN
? 0.32D
: 0.57D;
ParticleUtils.spawnParticles(
level,
pos,
new SculkChargeParticleOptions(roll),
spread,
direction,
velocities,
offset
);
}
} else {
for (Direction direction : DirectionUtils.unpack((byte)data)) {
float roll = direction == Direction.UP ? (float)Math.PI : 0.0F;
ParticleUtils.spawnParticles(level, pos, new SculkChargeParticleOptions(roll), spread, direction, velocities, 0.35D);
for (Direction direction : DirectionUtils.unpack((byte) data)) {
float roll = direction == Direction.UP ? (float) Math.PI : 0.0F;
ParticleUtils.spawnParticles(
level,
pos,
new SculkChargeParticleOptions(roll),
spread,
direction,
velocities,
0.35D
);
}
}
} else {
if (client != null) client.playLocalSound(pos, WBSoundEvents.BLOCK_SCULK_CHARGE, SoundSource.BLOCKS, 1.0F, 1.0F, false);
boolean fullBlock = level.getBlockState(pos).isCollisionShapeFullBlock(level, pos);
if (client != null)
client.playLocalSound(
pos,
WBSoundEvents.BLOCK_SCULK_CHARGE,
SoundSource.BLOCKS,
1.0F,
1.0F,
false
);
boolean fullBlock
= level.getBlockState(pos).isCollisionShapeFullBlock(level, pos);
int tries = fullBlock ? 40 : 20;
float spread = fullBlock ? 0.45F : 0.25F;
@ -381,7 +528,18 @@ public class SculkSpreadManager {
float x = 2.0F * random.nextFloat() - 1.0F;
float y = 2.0F * random.nextFloat() - 1.0F;
float z = 2.0F * random.nextFloat() - 1.0F;
if (server != null) server.sendParticles(WBParticleTypes.SCULK_CHARGE_POP.get(), (double)pos.getX() + 0.5D + (double)(x * spread), (double)pos.getY() + 0.5D + (double)(y * spread), (double)pos.getZ() + 0.5D + (double)(z * spread), 1, x * 0.07F, y * 0.07F, z * 0.07F, 0.0D);
if (server != null)
server.sendParticles(
WBParticleTypes.SCULK_CHARGE_POP.get(),
(double) pos.getX() + 0.5D + (double) (x * spread),
(double) pos.getY() + 0.5D + (double) (y * spread),
(double) pos.getZ() + 0.5D + (double) (z * spread),
1,
x * 0.07F,
y * 0.07F,
z * 0.07F,
0.0D
);
}
}
}

View file

@ -1,5 +1,8 @@
package com.cursedcauldron.wildbackport.common.blocks;
import java.util.Collection;
import java.util.Random;
import com.cursedcauldron.wildbackport.common.registry.WBBlocks;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
@ -8,24 +11,40 @@ import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.material.Fluids;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.Random;
public interface SculkSpreadable {
SculkSpreadable DEFAULT = new SculkSpreadable() {
@Override
public boolean spread(LevelAccessor level, BlockPos pos, BlockState state, @Nullable Collection<Direction> directions, boolean postProcess) {
public boolean spread(
LevelAccessor level,
BlockPos pos,
BlockState state,
@Nullable Collection<Direction> directions,
boolean postProcess
) {
if (directions == null) {
return ((SculkVeinBlock)WBBlocks.SCULK_VEIN.get()).getSamePositionOnlyGrower().grow(level.getBlockState(pos), level, pos, postProcess) > 0L;
} else if(!directions.isEmpty()) {
return (state.isAir() || state.getFluidState().is(Fluids.WATER)) && SculkVeinBlock.place(level, pos, state, directions);
return ((SculkVeinBlock) WBBlocks.SCULK_VEIN.get())
.getSamePositionOnlyGrower()
.grow(level.getBlockState(pos), level, pos, postProcess)
> 0L;
} else if (!directions.isEmpty()) {
return (state.isAir() || state.getFluidState().is(Fluids.WATER))
&& SculkVeinBlock.place(level, pos, state, directions);
} else {
return SculkSpreadable.super.spread(level, pos, state, directions, postProcess);
return SculkSpreadable.super.spread(
level, pos, state, directions, postProcess
);
}
}
@Override
public int spread(SculkSpreadManager.Cursor cursor, LevelAccessor level, BlockPos pos, Random random, SculkSpreadManager spreadManager, boolean shouldConvert) {
public int spread(
SculkSpreadManager.Cursor cursor,
LevelAccessor level,
BlockPos pos,
Random random,
SculkSpreadManager spreadManager,
boolean shouldConvert
) {
return cursor.getDecayDelay() > 0 ? cursor.getCharge() : 0;
}
@ -39,10 +58,21 @@ public interface SculkSpreadable {
return 1;
}
default void spreadAtSamePosition(LevelAccessor level, BlockState state, BlockPos pos, Random random) {}
default void spreadAtSamePosition(
LevelAccessor level, BlockState state, BlockPos pos, Random random
) {}
default boolean spread(LevelAccessor level, BlockPos pos, BlockState state, @Nullable Collection<Direction> directions, boolean postProcess) {
return ((SculkVeinBlock)WBBlocks.SCULK_VEIN.get()).getAllGrowTypeGrower().grow(state, level, pos, postProcess) > 0L;
default boolean spread(
LevelAccessor level,
BlockPos pos,
BlockState state,
@Nullable Collection<Direction> directions,
boolean postProcess
) {
return ((SculkVeinBlock) WBBlocks.SCULK_VEIN.get())
.getAllGrowTypeGrower()
.grow(state, level, pos, postProcess)
> 0L;
}
default boolean shouldConvertToSpreadable() {
@ -53,5 +83,12 @@ public interface SculkSpreadable {
return 1;
}
int spread(SculkSpreadManager.Cursor cursor, LevelAccessor level, BlockPos pos, Random random, SculkSpreadManager manager, boolean shouldConvert);
int spread(
SculkSpreadManager.Cursor cursor,
LevelAccessor level,
BlockPos pos,
Random random,
SculkSpreadManager manager,
boolean shouldConvert
);
}

View file

@ -1,10 +1,15 @@
package com.cursedcauldron.wildbackport.common.blocks;
import java.util.Collection;
import java.util.EnumSet;
import java.util.Random;
import java.util.Set;
import com.cursedcauldron.wildbackport.client.registry.WBSoundEvents;
import com.cursedcauldron.wildbackport.common.worldgen.VeinGrower;
import com.cursedcauldron.wildbackport.common.registry.WBBlocks;
import com.cursedcauldron.wildbackport.common.tag.WBBlockTags;
import com.cursedcauldron.wildbackport.common.utils.DirectionUtils;
import com.cursedcauldron.wildbackport.common.worldgen.VeinGrower;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.server.level.ServerLevel;
@ -26,17 +31,15 @@ import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.level.material.Fluids;
import net.minecraft.world.level.material.PushReaction;
import java.util.Collection;
import java.util.EnumSet;
import java.util.Random;
import java.util.Set;
//<>
public class SculkVeinBlock extends MultifaceBlock implements SculkSpreadable, SimpleWaterloggedBlock {
public class SculkVeinBlock
extends MultifaceBlock implements SculkSpreadable, SimpleWaterloggedBlock {
private static final BooleanProperty WATERLOGGED = BlockStateProperties.WATERLOGGED;
public final VeinGrower allGrowTypeGrower = new VeinGrower(new SculkVeinGrowChecker(VeinGrower.GROW_TYPES));
private final VeinGrower samePositionOnlyGrower = new VeinGrower(new SculkVeinGrowChecker(VeinGrower.GrowType.SAME_POSITION));
public final VeinGrower allGrowTypeGrower
= new VeinGrower(new SculkVeinGrowChecker(VeinGrower.GROW_TYPES));
private final VeinGrower samePositionOnlyGrower
= new VeinGrower(new SculkVeinGrowChecker(VeinGrower.GrowType.SAME_POSITION));
public SculkVeinBlock(Properties properties) {
super(properties);
@ -47,12 +50,16 @@ public class SculkVeinBlock extends MultifaceBlock implements SculkSpreadable, S
return this.allGrowTypeGrower;
}
public VeinGrower getSamePositionOnlyGrower() {
return this.samePositionOnlyGrower;
}
public static boolean place(LevelAccessor level, BlockPos pos, BlockState state, Collection<Direction> directions) {
public static boolean place(
LevelAccessor level,
BlockPos pos,
BlockState state,
Collection<Direction> directions
) {
boolean canPlace = false;
BlockState veinState = WBBlocks.SCULK_VEIN.get().defaultBlockState();
@ -77,11 +84,15 @@ public class SculkVeinBlock extends MultifaceBlock implements SculkSpreadable, S
}
@Override
public void spreadAtSamePosition(LevelAccessor level, BlockState state, BlockPos pos, Random random) {
public void spreadAtSamePosition(
LevelAccessor level, BlockState state, BlockPos pos, Random random
) {
if (state.is(this)) {
for (Direction direction : DIRECTIONS) {
BooleanProperty property = getFaceProperty(direction);
if (state.getValue(property) && level.getBlockState(pos.relative(direction)).is(WBBlocks.SCULK.get())) {
if (state.getValue(property)
&& level.getBlockState(pos.relative(direction))
.is(WBBlocks.SCULK.get())) {
state = state.setValue(property, false);
}
}
@ -97,15 +108,27 @@ public class SculkVeinBlock extends MultifaceBlock implements SculkSpreadable, S
}
@Override
public int spread(SculkSpreadManager.Cursor cursor, LevelAccessor level, BlockPos pos, Random random, SculkSpreadManager spreadManager, boolean shouldConvert) {
if (shouldConvert && this.convertToBlock(spreadManager, level, cursor.getPos(), random)) {
public int spread(
SculkSpreadManager.Cursor cursor,
LevelAccessor level,
BlockPos pos,
Random random,
SculkSpreadManager spreadManager,
boolean shouldConvert
) {
if (shouldConvert
&& this.convertToBlock(spreadManager, level, cursor.getPos(), random)) {
return cursor.getCharge() - 1;
} else {
return random.nextInt(spreadManager.getSpreadChance()) == 0 ? Mth.floor((float)cursor.getCharge() * 0.5F) : cursor.getCharge();
return random.nextInt(spreadManager.getSpreadChance()) == 0
? Mth.floor((float) cursor.getCharge() * 0.5F)
: cursor.getCharge();
}
}
private boolean convertToBlock(SculkSpreadManager spreadManager, LevelAccessor level, BlockPos pos, Random random) {
private boolean convertToBlock(
SculkSpreadManager spreadManager, LevelAccessor level, BlockPos pos, Random random
) {
BlockState state = level.getBlockState(pos);
TagKey<Block> replaceable = spreadManager.getReplaceableBlocks();
@ -116,9 +139,19 @@ public class SculkVeinBlock extends MultifaceBlock implements SculkSpreadable, S
if (blockState.is(replaceable)) {
BlockState sculk = WBBlocks.SCULK.get().defaultBlockState();
level.setBlock(blockPos, sculk, 3);
if (level instanceof ServerLevel server) Block.pushEntitiesUp(blockState, sculk, server, pos);
level.playSound(null, blockPos, WBSoundEvents.BLOCK_SCULK_SPREAD, SoundSource.BLOCKS, 1.0F, 1.0F);
this.allGrowTypeGrower.grow(sculk, level, blockPos, spreadManager.isWorldGen());
if (level instanceof ServerLevel server)
Block.pushEntitiesUp(blockState, sculk, server, pos);
level.playSound(
null,
blockPos,
WBSoundEvents.BLOCK_SCULK_SPREAD,
SoundSource.BLOCKS,
1.0F,
1.0F
);
this.allGrowTypeGrower.grow(
sculk, level, blockPos, spreadManager.isWorldGen()
);
Direction opposite = direction.getOpposite();
for (Direction towards : DIRECTIONS) {
@ -126,7 +159,9 @@ public class SculkVeinBlock extends MultifaceBlock implements SculkSpreadable, S
BlockPos targetPos = blockPos.relative(towards);
BlockState targetState = level.getBlockState(targetPos);
if (targetState.is(this)) {
this.spreadAtSamePosition(level, targetState, targetPos, random);
this.spreadAtSamePosition(
level, targetState, targetPos, random
);
}
}
}
@ -139,10 +174,13 @@ public class SculkVeinBlock extends MultifaceBlock implements SculkSpreadable, S
return false;
}
public static boolean veinCoversSculkReplaceable(LevelAccessor level, BlockState state, BlockPos pos) {
public static boolean
veinCoversSculkReplaceable(LevelAccessor level, BlockState state, BlockPos pos) {
if (state.is(WBBlocks.SCULK_VEIN.get())) {
for (Direction direction : DIRECTIONS) {
if (hasFace(state, direction) && level.getBlockState(pos.relative(direction)).is(WBBlockTags.SCULK_REPLACEABLE)) {
if (hasFace(state, direction)
&& level.getBlockState(pos.relative(direction))
.is(WBBlockTags.SCULK_REPLACEABLE)) {
return true;
}
}
@ -151,8 +189,11 @@ public class SculkVeinBlock extends MultifaceBlock implements SculkSpreadable, S
return false;
}
public boolean canGrowWithDirection(BlockGetter getter, BlockState state, BlockPos pos, Direction direction) {
if (this.isFaceSupported(direction) && (!state.is(this) || !hasFace(state, direction))) {
public boolean canGrowWithDirection(
BlockGetter getter, BlockState state, BlockPos pos, Direction direction
) {
if (this.isFaceSupported(direction)
&& (!state.is(this) || !hasFace(state, direction))) {
BlockPos blockPos = pos.relative(direction);
return canGrowOn(getter, direction, blockPos, getter.getBlockState(blockPos));
} else {
@ -161,27 +202,39 @@ public class SculkVeinBlock extends MultifaceBlock implements SculkSpreadable, S
}
@Override
public BlockState updateShape(BlockState state, Direction direction, BlockState neighborState, LevelAccessor world, BlockPos pos, BlockPos neighborPos) {
public BlockState updateShape(
BlockState state,
Direction direction,
BlockState neighborState,
LevelAccessor world,
BlockPos pos,
BlockPos neighborPos
) {
if (state.getValue(WATERLOGGED)) {
world.scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickDelay(world));
}
return super.updateShape(state, direction, neighborState, world, pos, neighborPos);
return super.updateShape(
state, direction, neighborState, world, pos, neighborPos
);
}
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
protected void
createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
super.createBlockStateDefinition(builder);
builder.add(WATERLOGGED);
}
@Override
public boolean canBeReplaced(BlockState state, BlockPlaceContext context) {
return !context.getItemInHand().is(WBBlocks.SCULK_VEIN.get().asItem()) || super.canBeReplaced(state, context);
return !context.getItemInHand().is(WBBlocks.SCULK_VEIN.get().asItem())
|| super.canBeReplaced(state, context);
}
@Override
public FluidState getFluidState(BlockState state) {
return state.getValue(WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(state);
return state.getValue(WATERLOGGED) ? Fluids.WATER.getSource(false)
: super.getFluidState(state);
}
@Override
@ -193,7 +246,7 @@ public class SculkVeinBlock extends MultifaceBlock implements SculkSpreadable, S
byte flag = 0;
for (Direction direction : directions) {
flag = (byte)(flag | 1 << direction.ordinal());
flag = (byte) (flag | 1 << direction.ordinal());
}
return flag;
@ -215,8 +268,14 @@ public class SculkVeinBlock extends MultifaceBlock implements SculkSpreadable, S
}
}
public static boolean canGrowOn(BlockGetter getter, Direction direction, BlockPos pos, BlockState state) {
return Block.isFaceFull(state.getBlockSupportShape(getter, pos), direction.getOpposite()) || Block.isFaceFull(state.getCollisionShape(getter, pos), direction.getOpposite());
public static boolean
canGrowOn(BlockGetter getter, Direction direction, BlockPos pos, BlockState state) {
return Block.isFaceFull(
state.getBlockSupportShape(getter, pos), direction.getOpposite()
)
|| Block.isFaceFull(
state.getCollisionShape(getter, pos), direction.getOpposite()
);
}
public static boolean hasFace(BlockState state, Direction direction) {
@ -233,21 +292,32 @@ public class SculkVeinBlock extends MultifaceBlock implements SculkSpreadable, S
}
@Override
public boolean canGrow(BlockGetter getter, BlockPos pos, BlockPos growPos, Direction direction, BlockState state) {
public boolean canGrow(
BlockGetter getter,
BlockPos pos,
BlockPos growPos,
Direction direction,
BlockState state
) {
BlockPos blockPos;
BlockState blockState = getter.getBlockState(growPos.relative(direction));
boolean flag = blockState.is(WBBlocks.SCULK.get()) || blockState.is(WBBlocks.SCULK_CATALYST.get()) || blockState.is(Blocks.MOVING_PISTON);
boolean flag = blockState.is(WBBlocks.SCULK.get())
|| blockState.is(WBBlocks.SCULK_CATALYST.get())
|| blockState.is(Blocks.MOVING_PISTON);
if (flag) {
return false;
}
if (pos.distManhattan(growPos) == 2 && getter.getBlockState(blockPos = pos.relative(direction.getOpposite())).isFaceSturdy(getter, blockPos, direction)) {
if (pos.distManhattan(growPos) == 2
&& getter.getBlockState(blockPos = pos.relative(direction.getOpposite()))
.isFaceSturdy(getter, blockPos, direction)) {
return false;
}
FluidState fluidState = state.getFluidState();
if (!fluidState.isEmpty() && !fluidState.is(Fluids.WATER)) {
return false;
}
return state.getMaterial().isReplaceable() || super.canGrow(getter, pos, growPos, direction, state);
return state.getMaterial().isReplaceable()
|| super.canGrow(getter, pos, growPos, direction, state);
}
@Override

View file

@ -9,21 +9,25 @@ import net.minecraft.world.level.block.state.properties.IntegerProperty;
public class StateProperties {
// Block Properties
public static final BooleanProperty SHRIEKING = BooleanProperty.create("shrieking");
public static final BooleanProperty CAN_SUMMON = BooleanProperty.create("can_summon");
public static final BooleanProperty BLOOM = BooleanProperty.create("bloom");
public static final IntegerProperty AGE_4 = IntegerProperty.create("age", 0, 4);
public static final BooleanProperty SHRIEKING = BooleanProperty.create("shrieking");
public static final BooleanProperty CAN_SUMMON = BooleanProperty.create("can_summon");
public static final BooleanProperty BLOOM = BooleanProperty.create("bloom");
public static final IntegerProperty AGE_4 = IntegerProperty.create("age", 0, 4);
// Block values
public static boolean always(BlockState state, BlockGetter getter, BlockPos pos, EntityType<?> type) {
public static boolean
always(BlockState state, BlockGetter getter, BlockPos pos, EntityType<?> type) {
return true;
}
public static boolean never(BlockState state, BlockGetter getter, BlockPos pos, EntityType<?> type) {
public static boolean
never(BlockState state, BlockGetter getter, BlockPos pos, EntityType<?> type) {
return false;
}
public static boolean ocelotOrParrot(BlockState state, BlockGetter getter, BlockPos pos, EntityType<?> entity) {
public static boolean ocelotOrParrot(
BlockState state, BlockGetter getter, BlockPos pos, EntityType<?> entity
) {
return entity == EntityType.OCELOT || entity == EntityType.PARROT;
}

View file

@ -27,7 +27,8 @@ import org.jetbrains.annotations.Nullable;
//<>
public class SculkCatalystBlockEntity extends BlockEntity implements GameEventListener {
private final BlockPositionSource positionSource = new BlockPositionSource(this.worldPosition);
private final BlockPositionSource positionSource
= new BlockPositionSource(this.worldPosition);
private final SculkSpreadManager spreadManager = SculkSpreadManager.create();
public SculkCatalystBlockEntity(BlockPos pos, BlockState state) {
@ -45,23 +46,39 @@ public class SculkCatalystBlockEntity extends BlockEntity implements GameEventLi
}
@Override
public boolean handleGameEvent(Level level, GameEvent event, @Nullable Entity entity, BlockPos pos) {
public boolean
handleGameEvent(Level level, GameEvent event, @Nullable Entity entity, BlockPos pos) {
if (!this.isRemoved()) {
if (event == WBGameEvents.ENTITY_DIE.get()) {
if (entity instanceof LivingEntity living && living instanceof EntityExperience mob) {
if (entity instanceof LivingEntity living
&& living instanceof EntityExperience mob) {
if (!mob.isExpDropDisabled()) {
int charge = mob.getExpToDrop();
if (!living.isBaby() && charge > 0) {
this.spreadManager.spread(new BlockPos(PositionUtils.relative(PositionUtils.toVec(pos), Direction.UP, 0.5D)), charge);
this.spreadManager.spread(
new BlockPos(PositionUtils.relative(
PositionUtils.toVec(pos), Direction.UP, 0.5D
)),
charge
);
LivingEntity attacker = living.getLastHurtByMob();
if (attacker instanceof ServerPlayer player) {
DamageSource source = living.getLastDamageSource() == null ? DamageSource.playerAttack(player) : living.getLastDamageSource();
WBCriteriaTriggers.KILL_MOB_NEAR_SCULK_CATALYST.trigger(player, entity, source);
DamageSource source = living.getLastDamageSource() == null
? DamageSource.playerAttack(player)
: living.getLastDamageSource();
WBCriteriaTriggers.KILL_MOB_NEAR_SCULK_CATALYST.trigger(
player, entity, source
);
}
}
mob.disableExpDrop();
SculkCatalystBlock.bloom((ServerLevel) level, this.worldPosition, this.getBlockState(), level.getRandom());
SculkCatalystBlock.bloom(
(ServerLevel) level,
this.worldPosition,
this.getBlockState(),
level.getRandom()
);
}
return true;
@ -72,7 +89,8 @@ public class SculkCatalystBlockEntity extends BlockEntity implements GameEventLi
return false;
}
public static void tick(Level level, BlockPos pos, BlockState state, SculkCatalystBlockEntity catalyst) {
public static void
tick(Level level, BlockPos pos, BlockState state, SculkCatalystBlockEntity catalyst) {
catalyst.spreadManager.tick(level, pos, level.getRandom(), true);
}

View file

@ -1,11 +1,13 @@
package com.cursedcauldron.wildbackport.common.blocks.entity;
import java.util.OptionalInt;
import com.cursedcauldron.wildbackport.WildBackport;
import com.cursedcauldron.wildbackport.client.particle.ShriekParticleOptions;
import com.cursedcauldron.wildbackport.client.registry.WBSoundEvents;
import com.cursedcauldron.wildbackport.common.blocks.SculkShriekerBlock;
import com.cursedcauldron.wildbackport.common.entities.warden.VibrationHandler;
import com.cursedcauldron.wildbackport.common.entities.Warden;
import com.cursedcauldron.wildbackport.common.entities.warden.VibrationHandler;
import com.cursedcauldron.wildbackport.common.entities.warden.WardenSpawnHelper;
import com.cursedcauldron.wildbackport.common.entities.warden.WardenSpawnTracker;
import com.cursedcauldron.wildbackport.common.registry.WBBlockEntities;
@ -38,19 +40,21 @@ import net.minecraft.world.level.gameevent.GameEventListener;
import net.minecraft.world.phys.Vec3;
import org.jetbrains.annotations.Nullable;
import java.util.OptionalInt;
//<>
public class SculkShriekerBlockEntity extends BlockEntity implements VibrationHandler.VibrationConfig {
private static final Int2ObjectMap<SoundEvent> SOUND_BY_LEVEL = Util.make(new Int2ObjectOpenHashMap<>(), map -> {
map.put(1, WBSoundEvents.WARDEN_NEARBY_CLOSE);
map.put(2, WBSoundEvents.WARDEN_NEARBY_CLOSER);
map.put(3, WBSoundEvents.WARDEN_NEARBY_CLOSEST);
map.put(4, WBSoundEvents.WARDEN_LISTENING_ANGRY);
});
public class SculkShriekerBlockEntity
extends BlockEntity implements VibrationHandler.VibrationConfig {
private static final Int2ObjectMap<SoundEvent> SOUND_BY_LEVEL
= Util.make(new Int2ObjectOpenHashMap<>(), map -> {
map.put(1, WBSoundEvents.WARDEN_NEARBY_CLOSE);
map.put(2, WBSoundEvents.WARDEN_NEARBY_CLOSER);
map.put(3, WBSoundEvents.WARDEN_NEARBY_CLOSEST);
map.put(4, WBSoundEvents.WARDEN_LISTENING_ANGRY);
});
private int warningLevel;
private VibrationHandler listener = new VibrationHandler(new BlockPositionSource(this.worldPosition), 8, this, null, 0.0F, 0);
private VibrationHandler listener = new VibrationHandler(
new BlockPositionSource(this.worldPosition), 8, this, null, 0.0F, 0
);
public SculkShriekerBlockEntity(BlockPos pos, BlockState state) {
super(WBBlockEntities.SCULK_SHRIEKER.get(), pos, state);
@ -68,7 +72,10 @@ public class SculkShriekerBlockEntity extends BlockEntity implements VibrationHa
}
if (tag.contains("listener", 10)) {
VibrationHandler.codec(this).parse(new Dynamic<>(NbtOps.INSTANCE, tag.getCompound("listener"))).resultOrPartial(WildBackport.LOGGER::error).ifPresent(listener -> this.listener = listener);
VibrationHandler.codec(this)
.parse(new Dynamic<>(NbtOps.INSTANCE, tag.getCompound("listener")))
.resultOrPartial(WildBackport.LOGGER::error)
.ifPresent(listener -> this.listener = listener);
}
}
@ -76,7 +83,10 @@ public class SculkShriekerBlockEntity extends BlockEntity implements VibrationHa
protected void saveAdditional(CompoundTag tag) {
super.saveAdditional(tag);
tag.putInt("warning_level", this.warningLevel);
VibrationHandler.codec(this).encodeStart(NbtOps.INSTANCE, this.listener).resultOrPartial(WildBackport.LOGGER::error).ifPresent(listener -> tag.put("listener", listener));
VibrationHandler.codec(this)
.encodeStart(NbtOps.INSTANCE, this.listener)
.resultOrPartial(WildBackport.LOGGER::error)
.ifPresent(listener -> tag.put("listener", listener));
}
@Override
@ -85,8 +95,16 @@ public class SculkShriekerBlockEntity extends BlockEntity implements VibrationHa
}
@Override
public boolean shouldListen(ServerLevel level, GameEventListener listener, BlockPos pos, GameEvent event, @Nullable Entity entity) {
return !this.isRemoved() && !this.getBlockState().getValue(SculkShriekerBlock.SHRIEKING) && tryGetPlayer(entity) != null;
public boolean shouldListen(
ServerLevel level,
GameEventListener listener,
BlockPos pos,
GameEvent event,
@Nullable Entity entity
) {
return !this.isRemoved()
&& !this.getBlockState().getValue(SculkShriekerBlock.SHRIEKING)
&& tryGetPlayer(entity) != null;
}
@Nullable
@ -113,7 +131,15 @@ public class SculkShriekerBlockEntity extends BlockEntity implements VibrationHa
}
@Override
public void onSignalReceive(ServerLevel level, GameEventListener listener, BlockPos pos, GameEvent event, @Nullable Entity entity, @Nullable Entity source, float distance) {
public void onSignalReceive(
ServerLevel level,
GameEventListener listener,
BlockPos pos,
GameEvent event,
@Nullable Entity entity,
@Nullable Entity source,
float distance
) {
this.tryShriek(level, tryGetPlayer(source != null ? source : entity));
}
@ -130,7 +156,8 @@ public class SculkShriekerBlockEntity extends BlockEntity implements VibrationHa
}
private boolean tryToWarn(ServerLevel level, ServerPlayer player) {
OptionalInt warning = WardenSpawnTracker.tryWarn(level, this.getBlockPos(), player);
OptionalInt warning
= WardenSpawnTracker.tryWarn(level, this.getBlockPos(), player);
warning.ifPresent(warningLevel -> this.warningLevel = warningLevel);
return warning.isPresent();
}
@ -141,17 +168,38 @@ public class SculkShriekerBlockEntity extends BlockEntity implements VibrationHa
level.setBlock(pos, state.setValue(SculkShriekerBlock.SHRIEKING, true), 2);
level.scheduleTick(pos, state.getBlock(), 90);
level.playSound(null, pos.getX(), pos.getY(), pos.getZ(), WBSoundEvents.BLOCK_SCULK_SHRIEKER_SHRIEK, SoundSource.BLOCKS, 2.0F, 0.6F + level.random.nextFloat() * 0.4F);
level.playSound(
null,
pos.getX(),
pos.getY(),
pos.getZ(),
WBSoundEvents.BLOCK_SCULK_SHRIEKER_SHRIEK,
SoundSource.BLOCKS,
2.0F,
0.6F + level.random.nextFloat() * 0.4F
);
for (int i = 0; i < 10; i++) {
int delay = i * 5;
level.sendParticles(new ShriekParticleOptions(delay), pos.getX() + 0.5D, pos.getY() + SculkShriekerBlock.TOP_Y, pos.getZ() + 0.5D, 1, 0.0D, 0.0D, 0.0D, 0.0D);
level.sendParticles(
new ShriekParticleOptions(delay),
pos.getX() + 0.5D,
pos.getY() + SculkShriekerBlock.TOP_Y,
pos.getZ() + 0.5D,
1,
0.0D,
0.0D,
0.0D,
0.0D
);
}
level.gameEvent(entity, WBGameEvents.SHRIEK.get(), pos);
}
private boolean canRespond(ServerLevel level) {
return this.getBlockState().getValue(SculkShriekerBlock.CAN_SUMMON) && level.getDifficulty() != Difficulty.PEACEFUL && level.getGameRules().getBoolean(WBGameRules.DO_WARDEN_SPAWNING);
return this.getBlockState().getValue(SculkShriekerBlock.CAN_SUMMON)
&& level.getDifficulty() != Difficulty.PEACEFUL
&& level.getGameRules().getBoolean(WBGameRules.DO_WARDEN_SPAWNING);
}
public void tryRespond(ServerLevel level) {
@ -160,7 +208,9 @@ public class SculkShriekerBlockEntity extends BlockEntity implements VibrationHa
this.playWardenReplySound();
}
Warden.addDarknessToClosePlayers(level, Vec3.atCenterOf(this.getBlockPos()), null, 40);
Warden.addDarknessToClosePlayers(
level, Vec3.atCenterOf(this.getBlockPos()), null, 40
);
}
}
@ -176,7 +226,18 @@ public class SculkShriekerBlockEntity extends BlockEntity implements VibrationHa
}
private boolean trySummonWarden(ServerLevel level) {
return this.warningLevel >= 4 && WardenSpawnHelper.trySpawnMob(WBEntityTypes.WARDEN.get(), MobSpawnType.TRIGGERED, level, this.getBlockPos(), 20, 5, 6).isPresent();
return this.warningLevel >= 4
&& WardenSpawnHelper
.trySpawnMob(
WBEntityTypes.WARDEN.get(),
MobSpawnType.TRIGGERED,
level,
this.getBlockPos(),
20,
5,
6
)
.isPresent();
}
@Override

View file

@ -1,15 +1,15 @@
package com.cursedcauldron.wildbackport.common.effects;
import java.util.Optional;
import java.util.function.Supplier;
import net.minecraft.network.protocol.Packet;
import net.minecraft.world.effect.MobEffect;
import net.minecraft.world.effect.MobEffectInstance;
import java.util.Optional;
import java.util.function.Supplier;
public interface EffectFactor {
static EffectFactor of(MobEffect effect) {
return (EffectFactor)effect;
return (EffectFactor) effect;
}
MobEffect setFactorCalculationData(Supplier<FactorCalculationData> data);
@ -22,7 +22,7 @@ public interface EffectFactor {
interface Instance {
static Instance of(MobEffectInstance instance) {
return (Instance)instance;
return (Instance) instance;
}
void setFactorCalculationData(Optional<FactorCalculationData> data);
@ -32,7 +32,7 @@ public interface EffectFactor {
interface Network {
static Network of(Packet<?> packet) {
return (Network)packet;
return (Network) packet;
}
FactorCalculationData getFactorCalculationData();

View file

@ -8,23 +8,34 @@ import net.minecraft.world.effect.MobEffectInstance;
import net.minecraft.world.entity.LivingEntity;
public class FactorCalculationData {
public static final Codec<FactorCalculationData> CODEC = RecordCodecBuilder.create(instance -> {
return instance.group(ExtraCodecs.NON_NEGATIVE_INT.fieldOf("padding_duration").forGetter(data -> {
return data.paddingDuration;
}), Codec.FLOAT.fieldOf("factor_start").orElse(0.0F).forGetter(data -> {
return data.factorStart;
}), Codec.FLOAT.fieldOf("factor_target").orElse(1.0F).forGetter(data -> {
return data.factorTarget;
}), Codec.FLOAT.fieldOf("factor_current").orElse(0.0F).forGetter(data -> {
return data.factorCurrent;
}), ExtraCodecs.NON_NEGATIVE_INT.fieldOf("effect_changed_timestamp").orElse(0).forGetter(data -> {
return data.effectChangedTimestamp;
}), Codec.FLOAT.fieldOf("factor_previous_frame").orElse(0.0F).forGetter(data -> {
return data.factorPreviousFrame;
}), Codec.BOOL.fieldOf("had_effect_last_tick").orElse(false).forGetter(data -> {
return data.hadEffectLastTick;
})).apply(instance, FactorCalculationData::new);
});
public static final Codec<FactorCalculationData> CODEC = RecordCodecBuilder.create(
instance -> {
return instance
.group(
ExtraCodecs.NON_NEGATIVE_INT.fieldOf("padding_duration")
.forGetter(data -> { return data.paddingDuration; }),
Codec.FLOAT.fieldOf("factor_start").orElse(0.0F).forGetter(data -> {
return data.factorStart;
}),
Codec.FLOAT.fieldOf("factor_target").orElse(1.0F).forGetter(data -> {
return data.factorTarget;
}),
Codec.FLOAT.fieldOf("factor_current").orElse(0.0F).forGetter(data -> {
return data.factorCurrent;
}),
ExtraCodecs.NON_NEGATIVE_INT.fieldOf("effect_changed_timestamp")
.orElse(0)
.forGetter(data -> { return data.effectChangedTimestamp; }),
Codec.FLOAT.fieldOf("factor_previous_frame")
.orElse(0.0F)
.forGetter(data -> { return data.factorPreviousFrame; }),
Codec.BOOL.fieldOf("had_effect_last_tick")
.orElse(false)
.forGetter(data -> { return data.hadEffectLastTick; })
)
.apply(instance, FactorCalculationData::new);
}
);
private final int paddingDuration;
private float factorStart;
private float factorTarget;
@ -33,7 +44,15 @@ public class FactorCalculationData {
private float factorPreviousFrame;
private boolean hadEffectLastTick;
public FactorCalculationData(int paddingDuration, float factorStart, float factorTarget, float factorCurrent, int effectChangedTimestamp, float factorPreviousFrame, boolean hadEffectLastTick) {
public FactorCalculationData(
int paddingDuration,
float factorStart,
float factorTarget,
float factorCurrent,
int effectChangedTimestamp,
float factorPreviousFrame,
boolean hadEffectLastTick
) {
this.paddingDuration = paddingDuration;
this.factorStart = factorStart;
this.factorTarget = factorTarget;
@ -58,12 +77,18 @@ public class FactorCalculationData {
this.factorTarget = inRange ? 1.0F : 0.0F;
}
float delta = Mth.clamp(((float)this.effectChangedTimestamp - (float)instance.getDuration()) / (float)this.paddingDuration, 0.0F, 1.0F);
float delta = Mth.clamp(
((float) this.effectChangedTimestamp - (float) instance.getDuration())
/ (float) this.paddingDuration,
0.0F,
1.0F
);
this.factorCurrent = Mth.lerp(delta, this.factorCurrent, this.factorTarget);
}
public float lerp(LivingEntity entity, float factor) {
if (entity.isRemoved()) this.factorPreviousFrame = this.factorCurrent;
if (entity.isRemoved())
this.factorPreviousFrame = this.factorCurrent;
return Mth.lerp(factor, this.factorPreviousFrame, this.factorCurrent);
}

View file

@ -1,5 +1,9 @@
package com.cursedcauldron.wildbackport.common.entities;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
import com.cursedcauldron.wildbackport.client.registry.WBSoundEvents;
import com.cursedcauldron.wildbackport.common.entities.brain.AllayBrain;
import com.cursedcauldron.wildbackport.common.registry.entity.WBMemoryModules;
@ -46,16 +50,48 @@ import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.Vec3;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
//<>
public class Allay extends PathfinderMob implements InventoryCarrier {
protected static final ImmutableList<? extends SensorType<? extends Sensor<? super Allay>>> SENSORS = ImmutableList.of(SensorType.NEAREST_LIVING_ENTITIES, SensorType.NEAREST_PLAYERS, SensorType.HURT_BY, SensorType.NEAREST_ITEMS);
protected static final ImmutableList<MemoryModuleType<?>> MEMORIES = ImmutableList.of(MemoryModuleType.PATH, MemoryModuleType.LOOK_TARGET, MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES, MemoryModuleType.WALK_TARGET, MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE, MemoryModuleType.HURT_BY, MemoryModuleType.NEAREST_VISIBLE_WANTED_ITEM, WBMemoryModules.LIKED_PLAYER.get(), WBMemoryModules.LIKED_NOTEBLOCK.get(), WBMemoryModules.LIKED_NOTEBLOCK_COOLDOWN_TICKS.get(), WBMemoryModules.ITEM_PICKUP_COOLDOWN_TICKS.get());
public static final ImmutableList<Float> THROW_SOUND_PITCHES = ImmutableList.of(0.5625F, 0.625F, 0.75F, 0.9375F, 1.0F, 1.0F, 1.125F, 1.25F, 1.5F, 1.875F, 2.0F, 2.25F, 2.5F, 3.0F, 3.75F, 4.0F);
protected static final
ImmutableList<? extends SensorType<? extends Sensor<? super Allay>>> SENSORS
= ImmutableList.of(
SensorType.NEAREST_LIVING_ENTITIES,
SensorType.NEAREST_PLAYERS,
SensorType.HURT_BY,
SensorType.NEAREST_ITEMS
);
protected static final ImmutableList<MemoryModuleType<?>> MEMORIES = ImmutableList.of(
MemoryModuleType.PATH,
MemoryModuleType.LOOK_TARGET,
MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES,
MemoryModuleType.WALK_TARGET,
MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE,
MemoryModuleType.HURT_BY,
MemoryModuleType.NEAREST_VISIBLE_WANTED_ITEM,
WBMemoryModules.LIKED_PLAYER.get(),
WBMemoryModules.LIKED_NOTEBLOCK.get(),
WBMemoryModules.LIKED_NOTEBLOCK_COOLDOWN_TICKS.get(),
WBMemoryModules.ITEM_PICKUP_COOLDOWN_TICKS.get()
);
public static final ImmutableList<Float> THROW_SOUND_PITCHES = ImmutableList.of(
0.5625F,
0.625F,
0.75F,
0.9375F,
1.0F,
1.0F,
1.125F,
1.25F,
1.5F,
1.875F,
2.0F,
2.25F,
2.5F,
3.0F,
3.75F,
4.0F
);
private final SimpleContainer inventory = new SimpleContainer(1);
private float holdingTicks;
private float holdingTicksOld;
@ -76,13 +112,19 @@ public class Allay extends PathfinderMob implements InventoryCarrier {
return AllayBrain.create(this.brainProvider().makeBrain(dynamic));
}
@Override @SuppressWarnings("unchecked")
@Override
@SuppressWarnings("unchecked")
public Brain<Allay> getBrain() {
return (Brain<Allay>)super.getBrain();
return (Brain<Allay>) super.getBrain();
}
public static AttributeSupplier.Builder createAttributes() {
return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 20.0D).add(Attributes.FLYING_SPEED, 0.1F).add(Attributes.MOVEMENT_SPEED, 0.1F).add(Attributes.ATTACK_DAMAGE, 2.0D).add(Attributes.FOLLOW_RANGE, 48.0D);
return Mob.createMobAttributes()
.add(Attributes.MAX_HEALTH, 20.0D)
.add(Attributes.FLYING_SPEED, 0.1F)
.add(Attributes.MOVEMENT_SPEED, 0.1F)
.add(Attributes.ATTACK_DAMAGE, 2.0D)
.add(Attributes.FOLLOW_RANGE, 48.0D);
}
@Override
@ -121,15 +163,18 @@ public class Allay extends PathfinderMob implements InventoryCarrier {
}
@Override
public boolean causeFallDamage(float fallDistance, float damageMultiplier, DamageSource source) {
public boolean
causeFallDamage(float fallDistance, float damageMultiplier, DamageSource source) {
return false;
}
@Override
public boolean hurt(DamageSource source, float amount) {
if (source.getEntity() instanceof Player player) {
Optional<UUID> likedPlayer = this.getBrain().getMemory(WBMemoryModules.LIKED_PLAYER.get());
if (likedPlayer.isPresent() && player.getUUID().equals(likedPlayer.get())) return false;
Optional<UUID> likedPlayer
= this.getBrain().getMemory(WBMemoryModules.LIKED_PLAYER.get());
if (likedPlayer.isPresent() && player.getUUID().equals(likedPlayer.get()))
return false;
}
return super.hurt(source, amount);
@ -139,19 +184,26 @@ public class Allay extends PathfinderMob implements InventoryCarrier {
protected void playStepSound(BlockPos pos, BlockState state) {}
@Override
protected void checkFallDamage(double fallenDistance, boolean canLand, BlockState state, BlockPos pos) {}
protected void checkFallDamage(
double fallenDistance, boolean canLand, BlockState state, BlockPos pos
) {}
@Override @Nullable
@Override
@Nullable
protected SoundEvent getAmbientSound() {
return this.hasItemInSlot(EquipmentSlot.MAINHAND) ? WBSoundEvents.ALLAY_AMBIENT_WITH_ITEM : WBSoundEvents.ALLAY_AMBIENT_WITHOUT_ITEM;
return this.hasItemInSlot(EquipmentSlot.MAINHAND)
? WBSoundEvents.ALLAY_AMBIENT_WITH_ITEM
: WBSoundEvents.ALLAY_AMBIENT_WITHOUT_ITEM;
}
@Override @Nullable
@Override
@Nullable
protected SoundEvent getHurtSound(DamageSource source) {
return WBSoundEvents.ALLAY_HURT;
}
@Override @Nullable
@Override
@Nullable
protected SoundEvent getDeathSound() {
return WBSoundEvents.ALLAY_DEATH;
}
@ -164,16 +216,22 @@ public class Allay extends PathfinderMob implements InventoryCarrier {
@Override
protected void customServerAiStep() {
this.level.getProfiler().push("allayBrain");
this.getBrain().tick((ServerLevel)this.level, this);
this.getBrain().tick((ServerLevel) this.level, this);
this.level.getProfiler().pop();
this.level.getProfiler().push("allayActivityUpdate");
AllayBrain.updateActivities(this);
this.level.getProfiler().pop();
this.level.getProfiler().push("looting");
if (!this.level.isClientSide && this.canPickUpLoot() && this.isAlive() && !this.dead && this.level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) {
List<ItemEntity> items = this.level.getEntitiesOfClass(ItemEntity.class, this.getBoundingBox().inflate(1.0, 1.0, 1.0));
if (!this.level.isClientSide && this.canPickUpLoot() && this.isAlive()
&& !this.dead
&& this.level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) {
List<ItemEntity> items = this.level.getEntitiesOfClass(
ItemEntity.class, this.getBoundingBox().inflate(1.0, 1.0, 1.0)
);
for (ItemEntity item : items) {
if (item.isRemoved() || item.getItem().isEmpty() || item.hasPickUpDelay() || !this.wantsToPickUp(item.getItem())) continue;
if (item.isRemoved() || item.getItem().isEmpty() || item.hasPickUpDelay()
|| !this.wantsToPickUp(item.getItem()))
continue;
this.pickUpItem(item);
}
}
@ -184,7 +242,8 @@ public class Allay extends PathfinderMob implements InventoryCarrier {
@Override
public void aiStep() {
super.aiStep();
if (!this.level.isClientSide && this.isAlive() && this.tickCount % 10 == 0) this.heal(1.0F);
if (!this.level.isClientSide && this.isAlive() && this.tickCount % 10 == 0)
this.heal(1.0F);
}
@Override
@ -215,7 +274,9 @@ public class Allay extends PathfinderMob implements InventoryCarrier {
}
private boolean isOnItemPickupCooldown() {
return this.getBrain().checkMemory(WBMemoryModules.ITEM_PICKUP_COOLDOWN_TICKS.get(), MemoryStatus.VALUE_PRESENT);
return this.getBrain().checkMemory(
WBMemoryModules.ITEM_PICKUP_COOLDOWN_TICKS.get(), MemoryStatus.VALUE_PRESENT
);
}
@Override
@ -226,15 +287,33 @@ public class Allay extends PathfinderMob implements InventoryCarrier {
ItemStack stack = playerStack.copy();
stack.setCount(1);
this.setItemInHand(InteractionHand.MAIN_HAND, stack);
if (!player.getAbilities().instabuild) playerStack.shrink(1);
this.level.playSound(player, this, WBSoundEvents.ALLAY_ITEM_GIVEN, SoundSource.NEUTRAL, 2.0F, 1.0F);
this.getBrain().setMemory(WBMemoryModules.LIKED_PLAYER.get(), player.getUUID());
if (!player.getAbilities().instabuild)
playerStack.shrink(1);
this.level.playSound(
player,
this,
WBSoundEvents.ALLAY_ITEM_GIVEN,
SoundSource.NEUTRAL,
2.0F,
1.0F
);
this.getBrain().setMemory(
WBMemoryModules.LIKED_PLAYER.get(), player.getUUID()
);
return InteractionResult.SUCCESS;
} else if (!allayStack.isEmpty() && hand == InteractionHand.MAIN_HAND && playerStack.isEmpty()) {
this.setItemSlot(EquipmentSlot.MAINHAND, ItemStack.EMPTY);
this.level.playSound(player, this, WBSoundEvents.ALLAY_ITEM_TAKEN, SoundSource.NEUTRAL, 2.0F, 1.0F);
this.level.playSound(
player,
this,
WBSoundEvents.ALLAY_ITEM_TAKEN,
SoundSource.NEUTRAL,
2.0F,
1.0F
);
this.swing(InteractionHand.MAIN_HAND);
for (ItemStack stack : this.getInventory().removeAllItems()) BehaviorUtils.throwItem(this, stack, this.position());
for (ItemStack stack : this.getInventory().removeAllItems())
BehaviorUtils.throwItem(this, stack, this.position());
this.getBrain().eraseMemory(WBMemoryModules.LIKED_PLAYER.get());
player.addItem(allayStack);
return InteractionResult.SUCCESS;
@ -251,7 +330,8 @@ public class Allay extends PathfinderMob implements InventoryCarrier {
@Override
public boolean wantsToPickUp(ItemStack stack) {
ItemStack heldItem = this.getItemInHand(InteractionHand.MAIN_HAND);
return !heldItem.isEmpty() && heldItem.sameItemStackIgnoreDurability(stack) && this.inventory.canAddItem(stack);
return !heldItem.isEmpty() && heldItem.sameItemStackIgnoreDurability(stack)
&& this.inventory.canAddItem(stack);
}
@Override
@ -260,7 +340,8 @@ public class Allay extends PathfinderMob implements InventoryCarrier {
if (this.wantsToPickUp(stack)) {
SimpleContainer inventory = this.getInventory();
boolean canAdd = inventory.canAddItem(stack);
if (!canAdd) return;
if (!canAdd)
return;
this.onItemPickup(itemEntity);
this.take(itemEntity, stack.getCount());
@ -285,7 +366,8 @@ public class Allay extends PathfinderMob implements InventoryCarrier {
}
public float getHoldingItemAnimationProgress(float animationProgress) {
return Mth.lerp(animationProgress, this.holdingTicksOld, this.holdingTicks) / 5.0F;
return Mth.lerp(animationProgress, this.holdingTicksOld, this.holdingTicks)
/ 5.0F;
}
@Override

View file

@ -71,7 +71,8 @@ public class ChestBoat extends MangroveBoat implements Container, MenuProvider {
super.addAdditionalSaveData(tag);
if (this.lootTable != null) {
tag.putString("LootTable", this.lootTable.toString());
if (this.lootTableSeed != 0L) tag.putLong("LootTableSeed", this.lootTableSeed);
if (this.lootTableSeed != 0L)
tag.putLong("LootTableSeed", this.lootTableSeed);
} else {
ContainerHelper.saveAllItems(tag, this.stacks);
}
@ -96,14 +97,16 @@ public class ChestBoat extends MangroveBoat implements Container, MenuProvider {
Containers.dropContents(this.level, this, this);
if (!this.level.isClientSide) {
Entity entity = source.getDirectEntity();
if (entity != null && entity.getType() == EntityType.PLAYER) PiglinAi.angerNearbyPiglins((Player)entity, true);
if (entity != null && entity.getType() == EntityType.PLAYER)
PiglinAi.angerNearbyPiglins((Player) entity, true);
}
}
}
@Override
public void remove(Entity.RemovalReason reason) {
if (!this.level.isClientSide && reason.shouldDestroy()) Containers.dropContents(this.level, this, this);
if (!this.level.isClientSide && reason.shouldDestroy())
Containers.dropContents(this.level, this, this);
super.remove(reason);
}
@ -131,7 +134,8 @@ public class ChestBoat extends MangroveBoat implements Container, MenuProvider {
}
}
@Override @SuppressWarnings("UnnecessaryDefault")
@Override
@SuppressWarnings("UnnecessaryDefault")
public Item getDropItem() {
return switch (this.getBoatType()) {
case OAK -> WBItems.OAK_CHEST_BOAT.get();
@ -211,30 +215,37 @@ public class ChestBoat extends MangroveBoat implements Container, MenuProvider {
ChestBoat.this.setItem(slot, stack);
return true;
}
} : super.getSlot(slot);
}
@Override
public void setChanged() {}
@Override
public boolean stillValid(Player player) {
return !this.isRemoved() && this.position().closerThan(player.position(), 8.0D);
}
@Override
public boolean isEmpty() {
for (ItemStack stack : this.stacks) if (!stack.isEmpty()) return false;
return true;
}
@Override @Nullable
public AbstractContainerMenu createMenu(int i, Inventory inventory, Player player) {
if (this.lootTable == null || !player.isSpectator()) {
this.unpackLootTable(inventory.player);
return ChestMenu.threeRows(i, inventory, this);
} :
super.getSlot(slot);
}
return null;
}
}
@Override
public void setChanged() {}
@Override
public boolean stillValid(Player player) {
return !this.isRemoved()
&& this.position().closerThan(player.position(), 8.0D);
}
@Override
public boolean isEmpty() {
for (ItemStack stack : this.stacks)
if (!stack.isEmpty())
return false;
return true;
}
@Override
@Nullable
public AbstractContainerMenu createMenu(
int i, Inventory inventory, Player player
) {
if (this.lootTable == null || !player.isSpectator()) {
this.unpackLootTable(inventory.player);
return ChestMenu.threeRows(i, inventory, this);
}
return null;
}
}

View file

@ -1,9 +1,16 @@
package com.cursedcauldron.wildbackport.common.entities;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Objects;
import java.util.Optional;
import java.util.OptionalInt;
import java.util.Random;
import com.cursedcauldron.wildbackport.client.animation.api.AnimationState;
import com.cursedcauldron.wildbackport.client.registry.WBSoundEvents;
import com.cursedcauldron.wildbackport.common.entities.brain.FrogBrain;
import com.cursedcauldron.wildbackport.common.entities.access.api.Poses;
import com.cursedcauldron.wildbackport.common.entities.brain.FrogBrain;
import com.cursedcauldron.wildbackport.common.registry.entity.WBEntityTypes;
import com.cursedcauldron.wildbackport.common.registry.entity.WBMemoryModules;
import com.cursedcauldron.wildbackport.common.registry.entity.WBSensorTypes;
@ -66,21 +73,47 @@ import net.minecraft.world.level.pathfinder.PathFinder;
import net.minecraft.world.phys.Vec3;
import org.jetbrains.annotations.Nullable;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Objects;
import java.util.Optional;
import java.util.OptionalInt;
import java.util.Random;
//<>
public class Frog extends Animal {
public static final Ingredient FOOD = Ingredient.of(Items.SLIME_BALL);
protected static final ImmutableList<? extends SensorType<? extends Sensor<? super Frog>>> SENSORS = ImmutableList.of(SensorType.NEAREST_LIVING_ENTITIES, SensorType.HURT_BY, WBSensorTypes.FROG_ATTACKABLES.get(), WBSensorTypes.FROG_TEMPTATIONS.get(), WBSensorTypes.IS_IN_WATER.get());
protected static final ImmutableList<? extends MemoryModuleType<?>> MEMORIES = ImmutableList.of(MemoryModuleType.LOOK_TARGET, MemoryModuleType.NEAREST_LIVING_ENTITIES, MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES, MemoryModuleType.WALK_TARGET, MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE, MemoryModuleType.PATH, MemoryModuleType.BREED_TARGET, MemoryModuleType.LONG_JUMP_COOLDOWN_TICKS, MemoryModuleType.LONG_JUMP_MID_JUMP, MemoryModuleType.ATTACK_TARGET, MemoryModuleType.TEMPTING_PLAYER, MemoryModuleType.TEMPTATION_COOLDOWN_TICKS, MemoryModuleType.IS_TEMPTED, MemoryModuleType.HURT_BY, MemoryModuleType.HURT_BY_ENTITY, MemoryModuleType.NEAREST_ATTACKABLE, WBMemoryModules.IS_IN_WATER.get(), WBMemoryModules.IS_PREGNANT.get(), WBMemoryModules.UNREACHABLE_TONGUE_TARGETS.get());
private static final EntityDataAccessor<Integer> VARIANT = SynchedEntityData.defineId(Frog.class, EntityDataSerializers.INT);
private static final EntityDataAccessor<OptionalInt> TARGET = SynchedEntityData.defineId(Frog.class, EntityDataSerializers.OPTIONAL_UNSIGNED_INT);
protected static final
ImmutableList<? extends SensorType<? extends Sensor<? super Frog>>> SENSORS
= ImmutableList.of(
SensorType.NEAREST_LIVING_ENTITIES,
SensorType.HURT_BY,
WBSensorTypes.FROG_ATTACKABLES.get(),
WBSensorTypes.FROG_TEMPTATIONS.get(),
WBSensorTypes.IS_IN_WATER.get()
);
protected static final ImmutableList<? extends MemoryModuleType<?>> MEMORIES
= ImmutableList.of(
MemoryModuleType.LOOK_TARGET,
MemoryModuleType.NEAREST_LIVING_ENTITIES,
MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES,
MemoryModuleType.WALK_TARGET,
MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE,
MemoryModuleType.PATH,
MemoryModuleType.BREED_TARGET,
MemoryModuleType.LONG_JUMP_COOLDOWN_TICKS,
MemoryModuleType.LONG_JUMP_MID_JUMP,
MemoryModuleType.ATTACK_TARGET,
MemoryModuleType.TEMPTING_PLAYER,
MemoryModuleType.TEMPTATION_COOLDOWN_TICKS,
MemoryModuleType.IS_TEMPTED,
MemoryModuleType.HURT_BY,
MemoryModuleType.HURT_BY_ENTITY,
MemoryModuleType.NEAREST_ATTACKABLE,
WBMemoryModules.IS_IN_WATER.get(),
WBMemoryModules.IS_PREGNANT.get(),
WBMemoryModules.UNREACHABLE_TONGUE_TARGETS.get()
);
private static final EntityDataAccessor<Integer> VARIANT
= SynchedEntityData.defineId(Frog.class, EntityDataSerializers.INT);
private static final EntityDataAccessor<OptionalInt> TARGET
= SynchedEntityData.defineId(
Frog.class, EntityDataSerializers.OPTIONAL_UNSIGNED_INT
);
public final AnimationState longJumpingAnimationState = new AnimationState();
public final AnimationState croakingAnimationState = new AnimationState();
public final AnimationState usingTongueAnimationState = new AnimationState();
@ -107,9 +140,10 @@ public class Frog extends Animal {
return FrogBrain.create(this.brainProvider().makeBrain(dynamic));
}
@Override @SuppressWarnings("unchecked")
@Override
@SuppressWarnings("unchecked")
public Brain<Frog> getBrain() {
return (Brain<Frog>)super.getBrain();
return (Brain<Frog>) super.getBrain();
}
@Override
@ -124,7 +158,11 @@ public class Frog extends Animal {
}
public Optional<Entity> getFrogTarget() {
return this.entityData.get(TARGET).stream().mapToObj(this.level::getEntity).filter(Objects::nonNull).findFirst();
return this.entityData.get(TARGET)
.stream()
.mapToObj(this.level::getEntity)
.filter(Objects::nonNull)
.findFirst();
}
public void setFrogTarget(Entity entity) {
@ -167,17 +205,19 @@ public class Frog extends Animal {
}
private boolean shouldWalk() {
return this.onGround && this.getDeltaMovement().horizontalDistanceSqr() > 1.0E-6D && !this.isInWaterOrBubble();
return this.onGround && this.getDeltaMovement().horizontalDistanceSqr() > 1.0E-6D
&& !this.isInWaterOrBubble();
}
private boolean shouldSwim() {
return this.getDeltaMovement().horizontalDistanceSqr() > 1.0E-6D && this.isInWaterOrBubble();
return this.getDeltaMovement().horizontalDistanceSqr() > 1.0E-6D
&& this.isInWaterOrBubble();
}
@Override
protected void customServerAiStep() {
this.level.getProfiler().push("frogBrain");
this.getBrain().tick((ServerLevel)this.level, this);
this.getBrain().tick((ServerLevel) this.level, this);
this.level.getProfiler().pop();
this.level.getProfiler().push("frogActivityUpdate");
FrogBrain.updateActivities(this);
@ -238,10 +278,12 @@ public class Frog extends Animal {
return this.getPose() == pose;
}
@Nullable @Override
@Nullable
@Override
public AgeableMob getBreedOffspring(ServerLevel level, AgeableMob mob) {
Frog frog = WBEntityTypes.FROG.get().create(level);
if (frog != null) FrogBrain.coolDownLongJump(frog, level.getRandom());
if (frog != null)
FrogBrain.coolDownLongJump(frog, level.getRandom());
return frog;
}
@ -256,7 +298,8 @@ public class Frog extends Animal {
@Override
public void spawnChildFromBreeding(ServerLevel level, Animal partner) {
ServerPlayer player = this.getLoveCause();
if (player == null) player = partner.getLoveCause();
if (player == null)
player = partner.getLoveCause();
if (player != null) {
player.awardStat(Stats.ANIMALS_BRED);
@ -268,12 +311,25 @@ public class Frog extends Animal {
this.resetLove();
partner.resetLove();
this.getBrain().setMemory(WBMemoryModules.IS_PREGNANT.get(), Unit.INSTANCE);
level.broadcastEntityEvent(this, (byte)18);
if (level.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) level.addFreshEntity(new ExperienceOrb(level, this.getX(), this.getY(), this.getZ(), this.getRandom().nextInt(7) + 1));
level.broadcastEntityEvent(this, (byte) 18);
if (level.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT))
level.addFreshEntity(new ExperienceOrb(
level,
this.getX(),
this.getY(),
this.getZ(),
this.getRandom().nextInt(7) + 1
));
}
@Override
public SpawnGroupData finalizeSpawn(ServerLevelAccessor accessor, DifficultyInstance difficulty, MobSpawnType spawnType, @Nullable SpawnGroupData groupData, @Nullable CompoundTag tag) {
public SpawnGroupData finalizeSpawn(
ServerLevelAccessor accessor,
DifficultyInstance difficulty,
MobSpawnType spawnType,
@Nullable SpawnGroupData groupData,
@Nullable CompoundTag tag
) {
Holder<Biome> biome = accessor.getBiome(this.blockPosition());
if (biome.is(WBBiomeTags.SPAWNS_COLD_VARIANT_FROGS)) {
this.setVariant(Variant.COLD);
@ -287,20 +343,26 @@ public class Frog extends Animal {
}
public static AttributeSupplier.Builder createAttributes() {
return Mob.createMobAttributes().add(Attributes.MOVEMENT_SPEED, 1.0D).add(Attributes.MAX_HEALTH, 10.0D).add(Attributes.ATTACK_DAMAGE, 10.0D);
return Mob.createMobAttributes()
.add(Attributes.MOVEMENT_SPEED, 1.0D)
.add(Attributes.MAX_HEALTH, 10.0D)
.add(Attributes.ATTACK_DAMAGE, 10.0D);
}
@Nullable @Override
@Nullable
@Override
protected SoundEvent getAmbientSound() {
return WBSoundEvents.FROG_AMBIENT;
}
@Nullable @Override
@Nullable
@Override
protected SoundEvent getHurtSound(DamageSource source) {
return WBSoundEvents.FROG_HURT;
}
@Nullable @Override
@Nullable
@Override
protected SoundEvent getDeathSound() {
return WBSoundEvents.FROG_DEATH;
}
@ -343,7 +405,8 @@ public class Frog extends Animal {
}
public static boolean isValidFrogFood(LivingEntity entity) {
return (!(entity instanceof Slime slime) || slime.getSize() == 1) && entity.getType().is(WBEntityTypeTags.FROG_FOOD);
return (!(entity instanceof Slime slime) || slime.getSize() == 1)
&& entity.getType().is(WBEntityTypeTags.FROG_FOOD);
}
@Override
@ -356,14 +419,22 @@ public class Frog extends Animal {
return FOOD.test(stack);
}
public static boolean checkFrogSpawnRules(EntityType<? extends Animal> type, LevelAccessor accessor, MobSpawnType spawnType, BlockPos pos, Random random) {
return accessor.getBlockState(pos.below()).is(WBBlockTags.FROGS_SPAWNABLE_ON) && isBrightEnoughToSpawn(accessor, pos);
public static boolean checkFrogSpawnRules(
EntityType<? extends Animal> type,
LevelAccessor accessor,
MobSpawnType spawnType,
BlockPos pos,
Random random
) {
return accessor.getBlockState(pos.below()).is(WBBlockTags.FROGS_SPAWNABLE_ON)
&& isBrightEnoughToSpawn(accessor, pos);
}
class FrogLookController extends LookControl {
FrogLookController(Mob mobEntity) {
super(mobEntity);
}
@Override
protected boolean resetXRotOnTick() {
return Frog.this.getFrogTarget().isEmpty();
@ -371,7 +442,8 @@ public class Frog extends Animal {
}
static class FrogNodeEvaluator extends AmphibiousNodeEvaluator {
private final BlockPos.MutableBlockPos preferredBlock = new BlockPos.MutableBlockPos();
private final BlockPos.MutableBlockPos preferredBlock
= new BlockPos.MutableBlockPos();
public FrogNodeEvaluator(boolean penalizeDeepWater) {
super(penalizeDeepWater);
@ -381,7 +453,11 @@ public class Frog extends Animal {
public BlockPathTypes getBlockPathType(BlockGetter getter, int x, int y, int z) {
this.preferredBlock.set(x, y - 1, z);
BlockState state = getter.getBlockState(this.preferredBlock);
return state.is(WBBlockTags.FROG_PREFER_JUMP_TO) ? BlockPathTypes.OPEN : FrogNodeEvaluator.getBlockPathTypeStatic(getter, this.preferredBlock.move(Direction.UP));
return state.is(WBBlockTags.FROG_PREFER_JUMP_TO)
? BlockPathTypes.OPEN
: FrogNodeEvaluator.getBlockPathTypeStatic(
getter, this.preferredBlock.move(Direction.UP)
);
}
}
@ -389,6 +465,7 @@ public class Frog extends Animal {
FrogPathNavigator(Frog frog, Level level) {
super(frog, level);
}
@Override
protected PathFinder createPathFinder(int range) {
this.nodeEvaluator = new FrogNodeEvaluator(true);
@ -411,7 +488,10 @@ public class Frog extends Animal {
TEMPERATE(0, "temperate"),
WARM(1, "warm"),
COLD(2, "cold");
private static final Variant[] VARIANTS = Arrays.stream(Variant.values()).sorted(Comparator.comparingInt(Variant::getId)).toArray(Variant[]::new);
private static final Variant[] VARIANTS
= Arrays.stream(Variant.values())
.sorted(Comparator.comparingInt(Variant::getId))
.toArray(Variant[] ::new);
private final int id;
private final String name;

View file

@ -37,9 +37,12 @@ public class MangroveBoat extends Boat {
this.setDamage(this.getDamage() + amount * 10.0F);
this.markHurt();
this.gameEvent(GameEvent.ENTITY_DAMAGED, source.getEntity());
boolean isCreativePlayer = source.getEntity() instanceof Player player && player.getAbilities().instabuild;
boolean isCreativePlayer = source.getEntity() instanceof Player player
&& player.getAbilities().instabuild;
if (isCreativePlayer || this.getDamage() > 40.0F) {
if (!isCreativePlayer && this.level.getGameRules().getBoolean(GameRules.RULE_DOENTITYDROPS)) this.dropItems(source);
if (!isCreativePlayer
&& this.level.getGameRules().getBoolean(GameRules.RULE_DOENTITYDROPS))
this.dropItems(source);
this.discard();
}
@ -56,6 +59,8 @@ public class MangroveBoat extends Boat {
@Override
public Item getDropItem() {
return this.getBoatType() != BoatTypes.MANGROVE.get() ? super.getDropItem() : WBItems.MANGROVE_BOAT.get();
return this.getBoatType() != BoatTypes.MANGROVE.get()
? super.getDropItem()
: WBItems.MANGROVE_BOAT.get();
}
}

View file

@ -39,8 +39,20 @@ import org.jetbrains.annotations.Nullable;
public class Tadpole extends AbstractFish {
public static final int MAX_TADPOLE_AGE = Math.abs(-24000);
private int age;
protected static final ImmutableList<SensorType<? extends Sensor<? super Tadpole>>> SENSORS = ImmutableList.of(SensorType.NEAREST_LIVING_ENTITIES, SensorType.NEAREST_PLAYERS, SensorType.HURT_BY);
protected static final ImmutableList<MemoryModuleType<?>> MEMORIES = ImmutableList.of(MemoryModuleType.LOOK_TARGET, MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES, MemoryModuleType.WALK_TARGET, MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE, MemoryModuleType.PATH, MemoryModuleType.NEAREST_VISIBLE_ADULT);
protected static final ImmutableList<SensorType<? extends Sensor<? super Tadpole>>>
SENSORS = ImmutableList.of(
SensorType.NEAREST_LIVING_ENTITIES,
SensorType.NEAREST_PLAYERS,
SensorType.HURT_BY
);
protected static final ImmutableList<MemoryModuleType<?>> MEMORIES = ImmutableList.of(
MemoryModuleType.LOOK_TARGET,
MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES,
MemoryModuleType.WALK_TARGET,
MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE,
MemoryModuleType.PATH,
MemoryModuleType.NEAREST_VISIBLE_ADULT
);
public Tadpole(EntityType<? extends AbstractFish> type, Level level) {
super(type, level);
@ -63,7 +75,8 @@ public class Tadpole extends AbstractFish {
return TadpoleBrain.create(this.brainProvider().makeBrain(dynamic));
}
@Override @SuppressWarnings("unchecked")
@Override
@SuppressWarnings("unchecked")
public Brain<Tadpole> getBrain() {
return (Brain<Tadpole>) super.getBrain();
}
@ -76,7 +89,7 @@ public class Tadpole extends AbstractFish {
@Override
protected void customServerAiStep() {
this.level.getProfiler().push("tadpoleBrain");
this.getBrain().tick((ServerLevel)this.level, this);
this.getBrain().tick((ServerLevel) this.level, this);
this.level.getProfiler().pop();
this.level.getProfiler().push("tadpoleActivityUpdate");
TadpoleBrain.updateActivities(this);
@ -85,13 +98,16 @@ public class Tadpole extends AbstractFish {
}
public static AttributeSupplier.Builder createAttributes() {
return Mob.createMobAttributes().add(Attributes.MOVEMENT_SPEED, 1.0D).add(Attributes.MAX_HEALTH, 6.0D);
return Mob.createMobAttributes()
.add(Attributes.MOVEMENT_SPEED, 1.0D)
.add(Attributes.MAX_HEALTH, 6.0D);
}
@Override
public void aiStep() {
super.aiStep();
if (!this.level.isClientSide) this.setAge(this.age + 1);
if (!this.level.isClientSide)
this.setAge(this.age + 1);
}
@Override
@ -106,17 +122,20 @@ public class Tadpole extends AbstractFish {
this.setAge(tag.getInt("Age"));
}
@Override @Nullable
@Override
@Nullable
protected SoundEvent getAmbientSound() {
return null;
}
@Override @Nullable
@Override
@Nullable
protected SoundEvent getHurtSound(DamageSource source) {
return WBSoundEvents.TADPOLE_HURT;
}
@Override @Nullable
@Override
@Nullable
protected SoundEvent getDeathSound() {
return WBSoundEvents.TADPOLE_DEATH;
}
@ -128,7 +147,8 @@ public class Tadpole extends AbstractFish {
this.eatSlimeBall(player, stack);
return InteractionResult.sidedSuccess(this.level.isClientSide());
} else {
return Bucketable.bucketMobPickup(player, hand, this).orElse(super.mobInteract(player, hand));
return Bucketable.bucketMobPickup(player, hand, this)
.orElse(super.mobInteract(player, hand));
}
}
@ -177,8 +197,16 @@ public class Tadpole extends AbstractFish {
private void eatSlimeBall(Player player, ItemStack stack) {
this.decrementItem(player, stack);
this.increaseAge((int)((float)(this.getTicksUntilGrowth() / 20) * 0.1F));
this.level.addParticle(ParticleTypes.HAPPY_VILLAGER, this.getRandomX(1.0D), this.getRandomY() + 0.5D, this.getRandomZ(1.0D), 0.0D, 0.0D, 0.0D);
this.increaseAge((int) ((float) (this.getTicksUntilGrowth() / 20) * 0.1F));
this.level.addParticle(
ParticleTypes.HAPPY_VILLAGER,
this.getRandomX(1.0D),
this.getRandomY() + 0.5D,
this.getRandomZ(1.0D),
0.0D,
0.0D,
0.0D
);
}
private void decrementItem(Player player, ItemStack stack) {
@ -197,16 +225,26 @@ public class Tadpole extends AbstractFish {
private void setAge(int age) {
this.age = age;
if (this.age >= MAX_TADPOLE_AGE) this.growUp();
if (this.age >= MAX_TADPOLE_AGE)
this.growUp();
}
private void growUp() {
if (this.level instanceof ServerLevel server) {
Frog frog = WBEntityTypes.FROG.get().create(this.level);
if (frog == null) return;
if (frog == null)
return;
frog.moveTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot());
frog.finalizeSpawn(server, this.level.getCurrentDifficultyAt(frog.blockPosition()), MobSpawnType.CONVERSION, null, null);
frog.moveTo(
this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot()
);
frog.finalizeSpawn(
server,
this.level.getCurrentDifficultyAt(frog.blockPosition()),
MobSpawnType.CONVERSION,
null,
null
);
frog.setNoAi(this.isNoAi());
if (this.hasCustomName()) {
frog.setCustomName(this.getCustomName());

View file

@ -1,5 +1,10 @@
package com.cursedcauldron.wildbackport.common.entities;
import java.util.Collections;
import java.util.Optional;
import java.util.Random;
import javax.annotation.Nullable;
import com.cursedcauldron.wildbackport.WildBackport;
import com.cursedcauldron.wildbackport.client.animation.api.AnimationState;
import com.cursedcauldron.wildbackport.client.registry.WBSoundEvents;
@ -61,18 +66,14 @@ import net.minecraft.world.level.gameevent.GameEventListenerRegistrar;
import net.minecraft.world.level.pathfinder.BlockPathTypes;
import net.minecraft.world.phys.Vec3;
import javax.annotation.Nullable;
import java.util.Collections;
import java.util.Optional;
import java.util.Random;
//<>
public class Warden extends Monster implements VibrationHandler.VibrationConfig {
public static final byte PLAY_ATTACK_SOUND = 4;
public static final byte EARS_TWITCH = 61;
public static final byte SONIC_BOOM = 62;
private static final EntityDataAccessor<Integer> ANGER = SynchedEntityData.defineId(Warden.class, EntityDataSerializers.INT);
private static final EntityDataAccessor<Integer> ANGER
= SynchedEntityData.defineId(Warden.class, EntityDataSerializers.INT);
private int tendrilPitchEnd;
private int tendrilPitchStart;
private int heartPitchEnd;
@ -85,11 +86,14 @@ public class Warden extends Monster implements VibrationHandler.VibrationConfig
public AnimationState sonicBoomAnimationState = new AnimationState();
private final GameEventListenerRegistrar gameEventHandler;
private final VibrationHandler listener;
private WardenAngerManager angerManager = new WardenAngerManager(this::isValidTarget, Collections.emptyList());
private WardenAngerManager angerManager
= new WardenAngerManager(this::isValidTarget, Collections.emptyList());
public Warden(EntityType<? extends Monster> type, Level level) {
super(type, level);
this.listener = new VibrationHandler(new MobPositionSource(this, this.getEyeHeight()), 16, this);
this.listener = new VibrationHandler(
new MobPositionSource(this, this.getEyeHeight()), 16, this
);
this.gameEventHandler = new GameEventListenerRegistrar(this.listener);
this.xpReward = 5;
this.getNavigation().setCanFloat(true);
@ -103,18 +107,24 @@ public class Warden extends Monster implements VibrationHandler.VibrationConfig
@Override
public Packet<?> getAddEntityPacket() {
return new ClientboundAddEntityPacket(this, this.hasPose(Poses.EMERGING.get()) ? 1 : 0);
return new ClientboundAddEntityPacket(
this, this.hasPose(Poses.EMERGING.get()) ? 1 : 0
);
}
@Override
public void recreateFromPacket(ClientboundAddEntityPacket packet) {
super.recreateFromPacket(packet);
if (packet.getData() == 1) this.setPose(Poses.EMERGING.get());
if (packet.getData() == 1)
this.setPose(Poses.EMERGING.get());
}
@Override
public boolean checkSpawnObstruction(LevelReader reader) {
return super.checkSpawnObstruction(reader) && reader.noCollision(this, this.getType().getDimensions().makeBoundingBox(this.position()));
return super.checkSpawnObstruction(reader)
&& reader.noCollision(
this, this.getType().getDimensions().makeBoundingBox(this.position())
);
}
@Override
@ -124,7 +134,8 @@ public class Warden extends Monster implements VibrationHandler.VibrationConfig
@Override
public boolean isInvulnerableTo(DamageSource source) {
return this.isDiggingOrEmerging() && !source.isBypassInvul() || super.isInvulnerableTo(source);
return this.isDiggingOrEmerging() && !source.isBypassInvul()
|| super.isInvulnerableTo(source);
}
private boolean isDiggingOrEmerging() {
@ -142,7 +153,12 @@ public class Warden extends Monster implements VibrationHandler.VibrationConfig
}
public static AttributeSupplier.Builder createAttributes() {
return Monster.createMonsterAttributes().add(Attributes.MAX_HEALTH, 500.0D).add(Attributes.MOVEMENT_SPEED, 0.3F).add(Attributes.KNOCKBACK_RESISTANCE, 1.0D).add(Attributes.ATTACK_KNOCKBACK, 1.5D).add(Attributes.ATTACK_DAMAGE, 30.0D);
return Monster.createMonsterAttributes()
.add(Attributes.MAX_HEALTH, 500.0D)
.add(Attributes.MOVEMENT_SPEED, 0.3F)
.add(Attributes.KNOCKBACK_RESISTANCE, 1.0D)
.add(Attributes.ATTACK_KNOCKBACK, 1.5D)
.add(Attributes.ATTACK_DAMAGE, 30.0D);
}
@Override
@ -158,7 +174,9 @@ public class Warden extends Monster implements VibrationHandler.VibrationConfig
@Nullable
@Override
protected SoundEvent getAmbientSound() {
return !this.hasPose(Poses.ROARING.get()) && !this.isDiggingOrEmerging() ? this.getAngriness().getSound() : null;
return !this.hasPose(Poses.ROARING.get()) && !this.isDiggingOrEmerging()
? this.getAngriness().getSound()
: null;
}
@Override
@ -178,7 +196,7 @@ public class Warden extends Monster implements VibrationHandler.VibrationConfig
@Override
public boolean doHurtTarget(Entity entity) {
this.level.broadcastEntityEvent(this, (byte)4);
this.level.broadcastEntityEvent(this, (byte) 4);
this.playSound(WBSoundEvents.WARDEN_ATTACK_IMPACT, 10.0F, this.getVoicePitch());
SonicBoom.setCooldown(this, 40);
return super.doHurtTarget(entity);
@ -212,7 +230,16 @@ public class Warden extends Monster implements VibrationHandler.VibrationConfig
if (this.tickCount % this.getHeartRate() == 0) {
this.heartPitchEnd = 10;
if (!this.isSilent()) {
this.level.playLocalSound(this.getX(), this.getY(), this.getZ(), WBSoundEvents.WARDEN_HEARTBEAT, this.getSoundSource(), 5.0F, this.getVoicePitch(), false);
this.level.playLocalSound(
this.getX(),
this.getY(),
this.getZ(),
WBSoundEvents.WARDEN_HEARTBEAT,
this.getSoundSource(),
5.0F,
this.getVoicePitch(),
false
);
}
}
@ -238,7 +265,7 @@ public class Warden extends Monster implements VibrationHandler.VibrationConfig
@Override
protected void customServerAiStep() {
ServerLevel level = (ServerLevel)this.level;
ServerLevel level = (ServerLevel) this.level;
level.getProfiler().push("wardenBrain");
this.getBrain().tick(level, this);
this.level.getProfiler().pop();
@ -270,27 +297,51 @@ public class Warden extends Monster implements VibrationHandler.VibrationConfig
}
private int getHeartRate() {
return 40 - Mth.floor(Mth.clamp((float)this.getAnger() / (float)Angriness.ANGRY.getThreshold(), 0.0F, 1.0F) * 30.0F);
return 40
- Mth.floor(
Mth.clamp(
(float) this.getAnger() / (float) Angriness.ANGRY.getThreshold(),
0.0F,
1.0F
)
* 30.0F
);
}
public float getTendrilPitch(float tickDelta) {
return Mth.lerp(tickDelta, (float)this.tendrilPitchStart, (float)this.tendrilPitchEnd) / 10.0F;
return Mth.lerp(
tickDelta, (float) this.tendrilPitchStart, (float) this.tendrilPitchEnd
)
/ 10.0F;
}
public float getHeartPitch(float tickDelta) {
return Mth.lerp(tickDelta, (float)this.heartPitchStart, (float)this.heartPitchEnd) / 10.0F;
return Mth.lerp(
tickDelta, (float) this.heartPitchStart, (float) this.heartPitchEnd
)
/ 10.0F;
}
private void addDigParticles(AnimationState animationState) {
if ((float)animationState.runningTime() < 4500.0F) {
if ((float) animationState.runningTime() < 4500.0F) {
Random random = this.getRandom();
BlockState state = this.getBlockStateOn();
if (state.getRenderShape() != RenderShape.INVISIBLE) {
for (int i = 0; i < 30; i++) {
double x = this.getX() + (double)Mth.randomBetween(random, -0.7F, 0.7F);
double x
= this.getX() + (double) Mth.randomBetween(random, -0.7F, 0.7F);
double y = this.getY();
double z = this.getZ() + (double)Mth.randomBetween(random, -0.7F, 0.7F);
this.level.addParticle(new BlockParticleOption(ParticleTypes.BLOCK, state), x, y, z, 0.0D, 0.0D, 0.0D);
double z
= this.getZ() + (double) Mth.randomBetween(random, -0.7F, 0.7F);
this.level.addParticle(
new BlockParticleOption(ParticleTypes.BLOCK, state),
x,
y,
z,
0.0D,
0.0D,
0.0D
);
}
}
}
@ -327,9 +378,10 @@ public class Warden extends Monster implements VibrationHandler.VibrationConfig
return WardenBrain.makeBrain(this, dynamic);
}
@Override @SuppressWarnings("unchecked")
@Override
@SuppressWarnings("unchecked")
public Brain<Warden> getBrain() {
return (Brain<Warden>)super.getBrain();
return (Brain<Warden>) super.getBrain();
}
@Override
@ -350,35 +402,53 @@ public class Warden extends Monster implements VibrationHandler.VibrationConfig
public boolean isValidTarget(@Nullable Entity entity) {
if (entity instanceof LivingEntity living) {
return this.level == entity.level && EntitySelector.NO_CREATIVE_OR_SPECTATOR.test(entity) && !this.isAlliedTo(entity) && living.getType() != EntityType.ARMOR_STAND && living.getType() != WBEntityTypes.WARDEN.get() && !living.isInvulnerable() && !living.isDeadOrDying() && this.level.getWorldBorder().isWithinBounds(living.getBoundingBox());
return this.level == entity.level
&& EntitySelector.NO_CREATIVE_OR_SPECTATOR.test(entity)
&& !this.isAlliedTo(entity) && living.getType() != EntityType.ARMOR_STAND
&& living.getType() != WBEntityTypes.WARDEN.get()
&& !living.isInvulnerable() && !living.isDeadOrDying()
&& this.level.getWorldBorder().isWithinBounds(living.getBoundingBox());
}
return false;
}
public static void addDarknessToClosePlayers(ServerLevel world, Vec3 pos, @Nullable Entity entity, int range) {
MobEffectInstance instance = new MobEffectInstance(WBMobEffects.DARKNESS.get(), 260, 0, false, false);
MobUtils.addEffectToPlayersWithinDistance(world, entity, pos, range, instance, 200);
public static void addDarknessToClosePlayers(
ServerLevel world, Vec3 pos, @Nullable Entity entity, int range
) {
MobEffectInstance instance
= new MobEffectInstance(WBMobEffects.DARKNESS.get(), 260, 0, false, false);
MobUtils.addEffectToPlayersWithinDistance(
world, entity, pos, range, instance, 200
);
}
@Override
public void addAdditionalSaveData(CompoundTag tag) {
super.addAdditionalSaveData(tag);
WardenAngerManager.codec(this::isValidTarget).encodeStart(NbtOps.INSTANCE, this.angerManager).resultOrPartial(WildBackport.LOGGER::error).ifPresent(manager -> tag.put("anger", manager));
WardenAngerManager.codec(this::isValidTarget)
.encodeStart(NbtOps.INSTANCE, this.angerManager)
.resultOrPartial(WildBackport.LOGGER::error)
.ifPresent(manager -> tag.put("anger", manager));
}
@Override
public void readAdditionalSaveData(CompoundTag tag) {
super.readAdditionalSaveData(tag);
if (tag.contains("anger")) {
WardenAngerManager.codec(this::isValidTarget).parse(new Dynamic<>(NbtOps.INSTANCE, tag.get("anger"))).resultOrPartial(WildBackport.LOGGER::error).ifPresent(manager -> this.angerManager = manager);
WardenAngerManager.codec(this::isValidTarget)
.parse(new Dynamic<>(NbtOps.INSTANCE, tag.get("anger")))
.resultOrPartial(WildBackport.LOGGER::error)
.ifPresent(manager -> this.angerManager = manager);
this.updateAnger();
}
}
private void playListeningSound() {
if (!this.hasPose(Poses.ROARING.get())) this.playSound(this.getAngriness().getListeningSound(), 10.0F, this.getVoicePitch());
if (!this.hasPose(Poses.ROARING.get()))
this.playSound(
this.getAngriness().getListeningSound(), 10.0F, this.getVoicePitch()
);
}
public Angriness getAngriness() {
@ -400,18 +470,23 @@ public class Warden extends Monster implements VibrationHandler.VibrationConfig
public void increaseAngerAt(Entity entity, int amount, boolean listening) {
if (!this.isNoAi() && this.isValidTarget(entity)) {
WardenBrain.resetDigCooldown(this);
boolean targetNotPlayer = !(this.getBrain().getMemory(MemoryModuleType.ATTACK_TARGET).orElse(null) instanceof Player);
boolean targetNotPlayer
= !(this.getBrain().getMemory(MemoryModuleType.ATTACK_TARGET).orElse(null)
instanceof Player);
int anger = this.angerManager.increaseAngerAt(entity, amount);
if (entity instanceof Player && targetNotPlayer && Angriness.getForAnger(anger).isAngry()) {
if (entity instanceof Player && targetNotPlayer
&& Angriness.getForAnger(anger).isAngry()) {
this.getBrain().eraseMemory(MemoryModuleType.ATTACK_TARGET);
}
if (listening) this.playListeningSound();
if (listening)
this.playListeningSound();
}
}
public Optional<LivingEntity> getPrimeSuspect() {
return this.getAngriness().isAngry() ? this.angerManager.getPrimeSuspect() : Optional.empty();
return this.getAngriness().isAngry() ? this.angerManager.getPrimeSuspect()
: Optional.empty();
}
@Nullable
@ -427,11 +502,23 @@ public class Warden extends Monster implements VibrationHandler.VibrationConfig
@Nullable
@Override
public SpawnGroupData finalizeSpawn(ServerLevelAccessor level, DifficultyInstance instance, MobSpawnType spawn, @Nullable SpawnGroupData data, @Nullable CompoundTag tag) {
this.getBrain().setMemoryWithExpiry(WBMemoryModules.DIG_COOLDOWN.get(), Unit.INSTANCE, 1200L);
public SpawnGroupData finalizeSpawn(
ServerLevelAccessor level,
DifficultyInstance instance,
MobSpawnType spawn,
@Nullable SpawnGroupData data,
@Nullable CompoundTag tag
) {
this.getBrain().setMemoryWithExpiry(
WBMemoryModules.DIG_COOLDOWN.get(), Unit.INSTANCE, 1200L
);
if (spawn == MobSpawnType.TRIGGERED) {
this.setPose(Poses.EMERGING.get());
this.getBrain().setMemoryWithExpiry(WBMemoryModules.IS_EMERGING.get(), Unit.INSTANCE, WardenBrain.EMERGE_DURATION);
this.getBrain().setMemoryWithExpiry(
WBMemoryModules.IS_EMERGING.get(),
Unit.INSTANCE,
WardenBrain.EMERGE_DURATION
);
this.playSound(WBSoundEvents.WARDEN_AGITATED, 5.0F, 1.0F);
}
@ -444,8 +531,10 @@ public class Warden extends Monster implements VibrationHandler.VibrationConfig
if (!this.level.isClientSide && !this.isNoAi() && !this.isDiggingOrEmerging()) {
Entity entity = source.getEntity();
this.increaseAngerAt(entity, Angriness.ANGRY.getThreshold() + 20, false);
if (this.brain.getMemory(MemoryModuleType.ATTACK_TARGET).isEmpty() && entity instanceof LivingEntity living) {
if (!(source instanceof IndirectEntityDamageSource) || this.closerThan(living, 5.0D)) {
if (this.brain.getMemory(MemoryModuleType.ATTACK_TARGET).isEmpty()
&& entity instanceof LivingEntity living) {
if (!(source instanceof IndirectEntityDamageSource)
|| this.closerThan(living, 5.0D)) {
this.updateAttackTarget(living);
}
}
@ -464,7 +553,8 @@ public class Warden extends Monster implements VibrationHandler.VibrationConfig
@Override
public EntityDimensions getDimensions(Pose pose) {
EntityDimensions dimensions = super.getDimensions(pose);
return this.isDiggingOrEmerging() ? EntityDimensions.fixed(dimensions.width, 1.0F) : dimensions;
return this.isDiggingOrEmerging() ? EntityDimensions.fixed(dimensions.width, 1.0F)
: dimensions;
}
@Override
@ -474,8 +564,11 @@ public class Warden extends Monster implements VibrationHandler.VibrationConfig
@Override
protected void doPush(Entity entity) {
if (!this.isNoAi() && !this.getBrain().hasMemoryValue(WBMemoryModules.TOUCH_COOLDOWN.get())) {
this.getBrain().setMemoryWithExpiry(WBMemoryModules.TOUCH_COOLDOWN.get(), Unit.INSTANCE, 20L);
if (!this.isNoAi()
&& !this.getBrain().hasMemoryValue(WBMemoryModules.TOUCH_COOLDOWN.get())) {
this.getBrain().setMemoryWithExpiry(
WBMemoryModules.TOUCH_COOLDOWN.get(), Unit.INSTANCE, 20L
);
this.increaseAngerAt(entity);
WardenBrain.lookAtDisturbance(this, entity.blockPosition());
}
@ -484,8 +577,17 @@ public class Warden extends Monster implements VibrationHandler.VibrationConfig
}
@Override
public boolean shouldListen(ServerLevel level, GameEventListener listener, BlockPos pos, GameEvent event, @Nullable Entity entity) {
if (!this.isNoAi() && !this.isDeadOrDying() && !this.getBrain().hasMemoryValue(WBMemoryModules.VIBRATION_COOLDOWN.get()) && !this.isDiggingOrEmerging() && level.getWorldBorder().isWithinBounds(pos) && !this.isRemoved() && this.level == level) {
public boolean shouldListen(
ServerLevel level,
GameEventListener listener,
BlockPos pos,
GameEvent event,
@Nullable Entity entity
) {
if (!this.isNoAi() && !this.isDeadOrDying()
&& !this.getBrain().hasMemoryValue(WBMemoryModules.VIBRATION_COOLDOWN.get())
&& !this.isDiggingOrEmerging() && level.getWorldBorder().isWithinBounds(pos)
&& !this.isRemoved() && this.level == level) {
if (entity instanceof LivingEntity living) {
return this.isValidTarget(living);
}
@ -497,15 +599,29 @@ public class Warden extends Monster implements VibrationHandler.VibrationConfig
}
@Override
public void onSignalReceive(ServerLevel level, GameEventListener listener, BlockPos pos, GameEvent event, @Nullable Entity entity, @Nullable Entity source, float distance) {
public void onSignalReceive(
ServerLevel level,
GameEventListener listener,
BlockPos pos,
GameEvent event,
@Nullable Entity entity,
@Nullable Entity source,
float distance
) {
if (!this.isDeadOrDying()) {
this.brain.setMemoryWithExpiry(WBMemoryModules.VIBRATION_COOLDOWN.get(), Unit.INSTANCE, 40L);
level.broadcastEntityEvent(this, (byte)61);
this.playSound(WBSoundEvents.WARDEN_TENDRIL_CLICKS, 5.0F, this.getVoicePitch());
this.brain.setMemoryWithExpiry(
WBMemoryModules.VIBRATION_COOLDOWN.get(), Unit.INSTANCE, 40L
);
level.broadcastEntityEvent(this, (byte) 61);
this.playSound(
WBSoundEvents.WARDEN_TENDRIL_CLICKS, 5.0F, this.getVoicePitch()
);
BlockPos position = pos;
if (source != null) {
if (this.closerThan(source, 30.0D)) {
if (this.getBrain().hasMemoryValue(WBMemoryModules.RECENT_PROJECTILE.get())) {
if (this.getBrain().hasMemoryValue(
WBMemoryModules.RECENT_PROJECTILE.get()
)) {
if (this.isValidTarget(source)) {
position = source.blockPosition();
}
@ -516,14 +632,17 @@ public class Warden extends Monster implements VibrationHandler.VibrationConfig
}
}
this.getBrain().setMemoryWithExpiry(WBMemoryModules.RECENT_PROJECTILE.get(), Unit.INSTANCE, 100L);
this.getBrain().setMemoryWithExpiry(
WBMemoryModules.RECENT_PROJECTILE.get(), Unit.INSTANCE, 100L
);
} else {
this.increaseAngerAt(entity);
}
if (!this.getAngriness().isAngry()) {
Optional<LivingEntity> primeSuspect = this.angerManager.getPrimeSuspect();
if (source != null || primeSuspect.isEmpty() || primeSuspect.get() == entity) {
if (source != null || primeSuspect.isEmpty()
|| primeSuspect.get() == entity) {
WardenBrain.lookAtDisturbance(this, position);
}
}
@ -540,6 +659,7 @@ public class Warden extends Monster implements VibrationHandler.VibrationConfig
double x = entity.getX() - this.getX();
double y = entity.getY() - this.getY();
double z = entity.getZ() - this.getZ();
return Mth.lengthSquared(x, z) < Mth.square(xzRange) && Mth.square(y) < Mth.square(yRange);
return Mth.lengthSquared(x, z) < Mth.square(xzRange)
&& Mth.square(y) < Mth.square(yRange);
}
}

View file

@ -1,18 +1,18 @@
package com.cursedcauldron.wildbackport.common.entities.access;
import java.util.function.BiConsumer;
import javax.annotation.Nullable;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.entity.LevelCallback;
import net.minecraft.world.level.gameevent.GameEventListener;
import net.minecraft.world.level.gameevent.GameEventListenerRegistrar;
import javax.annotation.Nullable;
import java.util.function.BiConsumer;
public class Listener {
public interface Instance {
static Instance of(GameEventListenerRegistrar instance) {
return (Instance)instance;
return (Instance) instance;
}
void onPosCallback(Level level);
@ -27,15 +27,16 @@ public class Listener {
return MobInstance.class.cast(entity);
}
default void updateEventHandler(BiConsumer<GameEventListenerRegistrar, Level> callback) {
}
default void
updateEventHandler(BiConsumer<GameEventListenerRegistrar, Level> callback) {}
}
public interface Callback<T> extends LevelCallback<T> {
@SuppressWarnings("unchecked")
static <T> Callback<T> of(T entity) {
return (Callback<T>)entity;
return (Callback<T>) entity;
}
void onSectionChange(T entry);
}
}

View file

@ -1,13 +1,13 @@
package com.cursedcauldron.wildbackport.common.entities.access;
import java.util.Optional;
import net.minecraft.core.GlobalPos;
import net.minecraft.world.entity.player.Player;
import java.util.Optional;
public interface Recovery {
static Recovery of(Player player) {
return (Recovery)player;
return (Recovery) player;
}
Optional<GlobalPos> getLastDeathLocation();

View file

@ -1,5 +1,8 @@
package com.cursedcauldron.wildbackport.common.entities.access;
import java.util.Optional;
import java.util.UUID;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.Entity;
@ -7,12 +10,14 @@ import net.minecraft.world.entity.projectile.Projectile;
import net.minecraft.world.level.gameevent.vibrations.VibrationListener;
import org.jetbrains.annotations.Nullable;
import java.util.Optional;
import java.util.UUID;
public record Vibration(@Nullable UUID uuid, @Nullable UUID sourceUuid, @Nullable Entity entity) {
public record
Vibration(@Nullable UUID uuid, @Nullable UUID sourceUuid, @Nullable Entity entity) {
public Vibration(@Nullable Entity entity) {
this(entity == null ? null : entity.getUUID(), Vibration.getOwnerUuid(entity), entity);
this(
entity == null ? null : entity.getUUID(),
Vibration.getOwnerUuid(entity),
entity
);
}
@Nullable
@ -25,16 +30,21 @@ public record Vibration(@Nullable UUID uuid, @Nullable UUID sourceUuid, @Nullabl
}
public Optional<Entity> getEntity(ServerLevel level) {
return Optional.ofNullable(this.entity).or(() -> Optional.ofNullable(this.uuid).map(level::getEntity));
return Optional.ofNullable(this.entity)
.or(() -> Optional.ofNullable(this.uuid).map(level::getEntity));
}
public Optional<Entity> getOwner(ServerLevel level) {
return Optional.ofNullable(this.entity).filter(entity -> entity instanceof Projectile).map(entity -> (Projectile)entity).map(Projectile::getOwner).or(() -> Optional.ofNullable(this.sourceUuid).map(level::getEntity));
return Optional.ofNullable(this.entity)
.filter(entity -> entity instanceof Projectile)
.map(entity -> (Projectile) entity)
.map(Projectile::getOwner)
.or(() -> Optional.ofNullable(this.sourceUuid).map(level::getEntity));
}
public interface Instance {
static Instance of(VibrationListener listener) {
return (Instance)listener;
return (Instance) listener;
}
void setPos(BlockPos pos);

View file

@ -11,6 +11,6 @@ public interface WardenTracker {
}
static WardenTracker of(Player player) {
return (WardenTracker)player;
return (WardenTracker) player;
}
}

View file

@ -1,5 +1,8 @@
package com.cursedcauldron.wildbackport.common.entities.brain;
import java.util.Optional;
import java.util.UUID;
import com.cursedcauldron.wildbackport.common.entities.Allay;
import com.cursedcauldron.wildbackport.common.entities.brain.allay.FlyingRandomStroll;
import com.cursedcauldron.wildbackport.common.entities.brain.allay.GiveInventoryToLookTarget;
@ -33,9 +36,6 @@ import net.minecraft.world.entity.schedule.Activity;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Blocks;
import java.util.Optional;
import java.util.UUID;
//<>
public class AllayBrain {
@ -49,15 +49,54 @@ public class AllayBrain {
}
private static void addCoreActivities(Brain<Allay> brain) {
brain.addActivity(Activity.CORE, 0, ImmutableList.of(new Swim(0.8F), new AnimalPanic(2.5F), new LookAtTargetSink(45, 90), new MoveToTargetSink(), new CountDownCooldownTicks(WBMemoryModules.LIKED_NOTEBLOCK_COOLDOWN_TICKS.get()), new CountDownCooldownTicks(WBMemoryModules.ITEM_PICKUP_COOLDOWN_TICKS.get())));
brain.addActivity(
Activity.CORE,
0,
ImmutableList.of(
new Swim(0.8F),
new AnimalPanic(2.5F),
new LookAtTargetSink(45, 90),
new MoveToTargetSink(),
new CountDownCooldownTicks(
WBMemoryModules.LIKED_NOTEBLOCK_COOLDOWN_TICKS.get()
),
new CountDownCooldownTicks(WBMemoryModules.ITEM_PICKUP_COOLDOWN_TICKS.get(
))
)
);
}
private static void addIdleActivities(Brain<Allay> brain) {
brain.addActivityWithConditions(Activity.IDLE, ImmutableList.of(Pair.of(0, new GoToWantedItem<>(entity -> {
return true;
}, 1.75F, true, 32)), Pair.of(1, new GiveInventoryToLookTarget<>(AllayBrain::getLookTarget, 2.25F)), Pair.of(2, new StayCloseToTarget<>(AllayBrain::getLookTarget, 4, 16, 2.25F)), Pair.of(3, new RunSometimes<>(new SetEntityLookTarget(entity -> {
return true;
}, 6.0F), UniformInt.of(30, 60))), Pair.of(4, new RunOne<>(ImmutableList.of(Pair.of(new FlyingRandomStroll(1.0F), 2), Pair.of(new SetWalkTargetFromLookTarget(1.0F, 3), 2), Pair.of(new DoNothing(30, 60), 1))))), ImmutableSet.of());
brain.addActivityWithConditions(
Activity.IDLE,
ImmutableList.of(
Pair.of(
0, new GoToWantedItem<>(entity -> { return true; }, 1.75F, true, 32)
),
Pair.of(
1, new GiveInventoryToLookTarget<>(AllayBrain::getLookTarget, 2.25F)
),
Pair.of(
2, new StayCloseToTarget<>(AllayBrain::getLookTarget, 4, 16, 2.25F)
),
Pair.of(
3,
new RunSometimes<>(
new SetEntityLookTarget(entity -> { return true; }, 6.0F),
UniformInt.of(30, 60)
)
),
Pair.of(
4,
new RunOne<>(ImmutableList.of(
Pair.of(new FlyingRandomStroll(1.0F), 2),
Pair.of(new SetWalkTargetFromLookTarget(1.0F, 3), 2),
Pair.of(new DoNothing(30, 60), 1)
))
)
),
ImmutableSet.of()
);
}
public static void updateActivities(Allay allay) {
@ -67,7 +106,8 @@ public class AllayBrain {
public static void rememberNoteBlock(LivingEntity entity, BlockPos pos) {
Brain<?> brain = entity.getBrain();
GlobalPos globalPos = GlobalPos.of(entity.getLevel().dimension(), pos);
Optional<GlobalPos> noteblock = brain.getMemory(WBMemoryModules.LIKED_NOTEBLOCK.get());
Optional<GlobalPos> noteblock
= brain.getMemory(WBMemoryModules.LIKED_NOTEBLOCK.get());
if (noteblock.isEmpty()) {
brain.setMemory(WBMemoryModules.LIKED_NOTEBLOCK.get(), globalPos);
brain.setMemory(WBMemoryModules.LIKED_NOTEBLOCK_COOLDOWN_TICKS.get(), 600);
@ -78,20 +118,26 @@ public class AllayBrain {
private static Optional<PositionTracker> getLookTarget(LivingEntity entity) {
Brain<?> brain = entity.getBrain();
Optional<GlobalPos> likedNoteBlock = brain.getMemory(WBMemoryModules.LIKED_NOTEBLOCK.get());
Optional<GlobalPos> likedNoteBlock
= brain.getMemory(WBMemoryModules.LIKED_NOTEBLOCK.get());
if (likedNoteBlock.isPresent()) {
GlobalPos pos = likedNoteBlock.get();
if (shouldGoTowardsNoteBlock(entity, brain, pos)) return Optional.of(new BlockPosTracker(pos.pos().above()));
if (shouldGoTowardsNoteBlock(entity, brain, pos))
return Optional.of(new BlockPosTracker(pos.pos().above()));
brain.eraseMemory(WBMemoryModules.LIKED_NOTEBLOCK.get());
}
return getLikedLookTarget(entity);
}
private static boolean shouldGoTowardsNoteBlock(LivingEntity entity, Brain<?> brain, GlobalPos pos) {
Optional<Integer> cooldownTicks = brain.getMemory(WBMemoryModules.LIKED_NOTEBLOCK_COOLDOWN_TICKS.get());
private static boolean
shouldGoTowardsNoteBlock(LivingEntity entity, Brain<?> brain, GlobalPos pos) {
Optional<Integer> cooldownTicks
= brain.getMemory(WBMemoryModules.LIKED_NOTEBLOCK_COOLDOWN_TICKS.get());
Level level = entity.getLevel();
return level.dimension() == pos.dimension() && level.getBlockState(pos.pos()).is(Blocks.NOTE_BLOCK) && cooldownTicks.isPresent();
return level.dimension() == pos.dimension()
&& level.getBlockState(pos.pos()).is(Blocks.NOTE_BLOCK)
&& cooldownTicks.isPresent();
}
private static Optional<PositionTracker> getLikedLookTarget(LivingEntity entity) {
@ -101,10 +147,13 @@ public class AllayBrain {
public static Optional<ServerPlayer> getLikedPlayer(LivingEntity entity) {
Level level = entity.getLevel();
if (!level.isClientSide && level instanceof ServerLevel server) {
Optional<UUID> likedPlayer = entity.getBrain().getMemory(WBMemoryModules.LIKED_PLAYER.get());
Optional<UUID> likedPlayer
= entity.getBrain().getMemory(WBMemoryModules.LIKED_PLAYER.get());
if (likedPlayer.isPresent()) {
if (server.getEntity(likedPlayer.get()) instanceof ServerPlayer player) {
if ((player.gameMode.isSurvival() || player.gameMode.isCreative()) && player.closerThan(entity, 64.0D)) return Optional.of(player);
if ((player.gameMode.isSurvival() || player.gameMode.isCreative())
&& player.closerThan(entity, 64.0D))
return Optional.of(player);
}
return Optional.empty();

View file

@ -1,5 +1,7 @@
package com.cursedcauldron.wildbackport.common.entities.brain;
import java.util.Random;
import com.cursedcauldron.wildbackport.client.registry.WBSoundEvents;
import com.cursedcauldron.wildbackport.common.entities.Frog;
import com.cursedcauldron.wildbackport.common.entities.brain.frog.BiasedLongJumpTask;
@ -45,13 +47,14 @@ import net.minecraft.world.entity.schedule.Activity;
import net.minecraft.world.item.crafting.Ingredient;
import net.minecraft.world.level.block.Blocks;
import java.util.Random;
public class FrogBrain {
private static final UniformInt LONG_JUMP_COOLDOWN_RANGE = UniformInt.of(100, 140);
public static void coolDownLongJump(Frog frog, Random random) {
frog.getBrain().setMemory(MemoryModuleType.LONG_JUMP_COOLDOWN_TICKS, LONG_JUMP_COOLDOWN_RANGE.sample(random));
frog.getBrain().setMemory(
MemoryModuleType.LONG_JUMP_COOLDOWN_TICKS,
LONG_JUMP_COOLDOWN_RANGE.sample(random)
);
}
public static Brain<?> create(Brain<Frog> brain) {
@ -68,27 +71,200 @@ public class FrogBrain {
}
private static void addCoreActivities(Brain<Frog> brain) {
brain.addActivity(Activity.CORE, 0, ImmutableList.of(new AnimalPanic(2.0F), new LookAtTargetSink(45, 90), new MoveToTargetSink(), new CountDownCooldownTicks(MemoryModuleType.TEMPTATION_COOLDOWN_TICKS), new CountDownCooldownTicks(MemoryModuleType.LONG_JUMP_COOLDOWN_TICKS)));
brain.addActivity(
Activity.CORE,
0,
ImmutableList.of(
new AnimalPanic(2.0F),
new LookAtTargetSink(45, 90),
new MoveToTargetSink(),
new CountDownCooldownTicks(MemoryModuleType.TEMPTATION_COOLDOWN_TICKS),
new CountDownCooldownTicks(MemoryModuleType.LONG_JUMP_COOLDOWN_TICKS)
)
);
}
private static void addIdleActivities(Brain<Frog> brain) {
brain.addActivityWithConditions(Activity.IDLE, ImmutableList.of(Pair.of(0, new RunSometimes<LivingEntity>(new SetEntityLookTarget(EntityType.PLAYER, 6.0F), UniformInt.of(30, 60))), Pair.of(0, new AnimalMakeLove(WBEntityTypes.FROG.get(), 1.0F)), Pair.of(1, new FollowTemptation(entity -> 1.25F)), Pair.of(2, new StartAttacking<>(FrogBrain::isNotBreeding, frog -> frog.getBrain().getMemory(MemoryModuleType.NEAREST_ATTACKABLE))), Pair.of(3, new WalkTowardsLand(6, 1.0F)), Pair.of(4, new RunOne<>(ImmutableMap.of(MemoryModuleType.WALK_TARGET, MemoryStatus.VALUE_ABSENT), ImmutableList.of(Pair.of(new RandomStroll(1.0F), 1), Pair.of(new SetWalkTargetFromLookTarget(1.0F, 3), 1), Pair.of(new Croak(), 3), Pair.of(new RunIf<>(Entity::isOnGround, new DoNothing(5, 20)), 2))))), ImmutableSet.of(Pair.of(MemoryModuleType.LONG_JUMP_MID_JUMP, MemoryStatus.VALUE_ABSENT), Pair.of(WBMemoryModules.IS_IN_WATER.get(), MemoryStatus.VALUE_ABSENT)));
brain.addActivityWithConditions(
Activity.IDLE,
ImmutableList.of(
Pair.of(
0,
new RunSometimes<LivingEntity>(
new SetEntityLookTarget(EntityType.PLAYER, 6.0F),
UniformInt.of(30, 60)
)
),
Pair.of(0, new AnimalMakeLove(WBEntityTypes.FROG.get(), 1.0F)),
Pair.of(1, new FollowTemptation(entity -> 1.25F)),
Pair.of(
2,
new StartAttacking<>(
FrogBrain::isNotBreeding,
frog
-> frog.getBrain().getMemory(MemoryModuleType.NEAREST_ATTACKABLE)
)
),
Pair.of(3, new WalkTowardsLand(6, 1.0F)),
Pair.of(
4,
new RunOne<>(
ImmutableMap
.of(MemoryModuleType.WALK_TARGET, MemoryStatus.VALUE_ABSENT),
ImmutableList.of(
Pair.of(new RandomStroll(1.0F), 1),
Pair.of(new SetWalkTargetFromLookTarget(1.0F, 3), 1),
Pair.of(new Croak(), 3),
Pair.of(
new RunIf<>(Entity::isOnGround, new DoNothing(5, 20)), 2
)
)
)
)
),
ImmutableSet.of(
Pair.of(MemoryModuleType.LONG_JUMP_MID_JUMP, MemoryStatus.VALUE_ABSENT),
Pair.of(WBMemoryModules.IS_IN_WATER.get(), MemoryStatus.VALUE_ABSENT)
)
);
}
private static void addSwimActivities(Brain<Frog> brain) {
brain.addActivityWithConditions(WBActivities.SWIM.get(), ImmutableList.of(Pair.of(0, new RunSometimes<LivingEntity>(new SetEntityLookTarget(EntityType.PLAYER, 6.0F), UniformInt.of(30, 60))), Pair.of(1, new FollowTemptation(entity -> 1.25F)), Pair.of(2, new StartAttacking<>(FrogBrain::isNotBreeding, frog -> frog.getBrain().getMemory(MemoryModuleType.NEAREST_ATTACKABLE))), Pair.of(3, new WalkTowardsLand(8, 1.5F)), Pair.of(5, new GateBehavior<>(ImmutableMap.of(MemoryModuleType.WALK_TARGET, MemoryStatus.VALUE_ABSENT), ImmutableSet.of(), GateBehavior.OrderPolicy.ORDERED, GateBehavior.RunningPolicy.TRY_ALL, ImmutableList.of(Pair.of(new RandomStroll(0.75F), 1), Pair.of(new RandomStroll(1.0F, true), 1), Pair.of(new SetWalkTargetFromLookTarget(1.0F, 3), 1), Pair.of(new RunIf<>(Entity::isInWaterOrBubble, new DoNothing(30, 60)), 5))))), ImmutableSet.of(Pair.of(MemoryModuleType.LONG_JUMP_MID_JUMP, MemoryStatus.VALUE_ABSENT), Pair.of(WBMemoryModules.IS_IN_WATER.get(), MemoryStatus.VALUE_PRESENT)));
brain.addActivityWithConditions(
WBActivities.SWIM.get(),
ImmutableList.of(
Pair.of(
0,
new RunSometimes<LivingEntity>(
new SetEntityLookTarget(EntityType.PLAYER, 6.0F),
UniformInt.of(30, 60)
)
),
Pair.of(1, new FollowTemptation(entity -> 1.25F)),
Pair.of(
2,
new StartAttacking<>(
FrogBrain::isNotBreeding,
frog
-> frog.getBrain().getMemory(MemoryModuleType.NEAREST_ATTACKABLE)
)
),
Pair.of(3, new WalkTowardsLand(8, 1.5F)),
Pair.of(
5,
new GateBehavior<>(
ImmutableMap
.of(MemoryModuleType.WALK_TARGET, MemoryStatus.VALUE_ABSENT),
ImmutableSet.of(),
GateBehavior.OrderPolicy.ORDERED,
GateBehavior.RunningPolicy.TRY_ALL,
ImmutableList.of(
Pair.of(new RandomStroll(0.75F), 1),
Pair.of(new RandomStroll(1.0F, true), 1),
Pair.of(new SetWalkTargetFromLookTarget(1.0F, 3), 1),
Pair
.of(new RunIf<>(
Entity::isInWaterOrBubble, new DoNothing(30, 60)
),
5)
)
)
)
),
ImmutableSet.of(
Pair.of(MemoryModuleType.LONG_JUMP_MID_JUMP, MemoryStatus.VALUE_ABSENT),
Pair.of(WBMemoryModules.IS_IN_WATER.get(), MemoryStatus.VALUE_PRESENT)
)
);
}
private static void addLaySpawnActivities(Brain<Frog> brain) {
brain.addActivityWithConditions(WBActivities.LAY_SPAWN.get(), ImmutableList.of(Pair.of(0, new RunSometimes<LivingEntity>(new SetEntityLookTarget(EntityType.PLAYER, 6.0F), UniformInt.of(30, 60))), Pair.of(1, new StartAttacking<>(FrogBrain::isNotBreeding, frog -> frog.getBrain().getMemory(MemoryModuleType.NEAREST_ATTACKABLE))), Pair.of(2, new WalkTowardsWater(8, 1.0F)), Pair.of(3, new LayFrogSpawn(WBBlocks.FROGSPAWN.get(), WBMemoryModules.IS_PREGNANT.get())), Pair.of(4, new RunOne<>(ImmutableList.of(Pair.of(new RandomStroll(1.0F), 2), Pair.of(new SetWalkTargetFromLookTarget(1.0F, 3), 1), Pair.of(new Croak(), 2), Pair.of(new RunIf<>(Entity::isOnGround, new DoNothing(5, 20)), 1))))), ImmutableSet.of(Pair.of(MemoryModuleType.LONG_JUMP_MID_JUMP, MemoryStatus.VALUE_ABSENT), Pair.of(WBMemoryModules.IS_PREGNANT.get(), MemoryStatus.VALUE_PRESENT)));
brain.addActivityWithConditions(
WBActivities.LAY_SPAWN.get(),
ImmutableList.of(
Pair.of(
0,
new RunSometimes<LivingEntity>(
new SetEntityLookTarget(EntityType.PLAYER, 6.0F),
UniformInt.of(30, 60)
)
),
Pair.of(
1,
new StartAttacking<>(
FrogBrain::isNotBreeding,
frog
-> frog.getBrain().getMemory(MemoryModuleType.NEAREST_ATTACKABLE)
)
),
Pair.of(2, new WalkTowardsWater(8, 1.0F)),
Pair.of(
3,
new LayFrogSpawn(
WBBlocks.FROGSPAWN.get(), WBMemoryModules.IS_PREGNANT.get()
)
),
Pair.of(
4,
new RunOne<>(ImmutableList.of(
Pair.of(new RandomStroll(1.0F), 2),
Pair.of(new SetWalkTargetFromLookTarget(1.0F, 3), 1),
Pair.of(new Croak(), 2),
Pair.of(new RunIf<>(Entity::isOnGround, new DoNothing(5, 20)), 1)
))
)
),
ImmutableSet.of(
Pair.of(MemoryModuleType.LONG_JUMP_MID_JUMP, MemoryStatus.VALUE_ABSENT),
Pair.of(WBMemoryModules.IS_PREGNANT.get(), MemoryStatus.VALUE_PRESENT)
)
);
}
private static void addLongJumpActivities(Brain<Frog> brain) {
brain.addActivityWithConditions(Activity.LONG_JUMP, ImmutableList.of(Pair.of(0, new LongJumpMidJump(LONG_JUMP_COOLDOWN_RANGE, WBSoundEvents.FROG_STEP)), Pair.of(1, new BiasedLongJumpTask<>(LONG_JUMP_COOLDOWN_RANGE, 2, 4, 1.5F, frog -> WBSoundEvents.FROG_LONG_JUMP, WBBlockTags.FROG_PREFER_JUMP_TO, 0.5F, state -> state.is(Blocks.LILY_PAD)))), ImmutableSet.of(Pair.of(MemoryModuleType.TEMPTING_PLAYER, MemoryStatus.VALUE_ABSENT), Pair.of(MemoryModuleType.BREED_TARGET, MemoryStatus.VALUE_ABSENT), Pair.of(MemoryModuleType.LONG_JUMP_COOLDOWN_TICKS, MemoryStatus.VALUE_ABSENT), Pair.of(WBMemoryModules.IS_IN_WATER.get(), MemoryStatus.VALUE_ABSENT)));
brain.addActivityWithConditions(
Activity.LONG_JUMP,
ImmutableList.of(
Pair.of(
0,
new LongJumpMidJump(LONG_JUMP_COOLDOWN_RANGE, WBSoundEvents.FROG_STEP)
),
Pair.of(
1,
new BiasedLongJumpTask<>(
LONG_JUMP_COOLDOWN_RANGE,
2,
4,
1.5F,
frog
-> WBSoundEvents.FROG_LONG_JUMP,
WBBlockTags.FROG_PREFER_JUMP_TO,
0.5F,
state -> state.is(Blocks.LILY_PAD)
)
)
),
ImmutableSet.of(
Pair.of(MemoryModuleType.TEMPTING_PLAYER, MemoryStatus.VALUE_ABSENT),
Pair.of(MemoryModuleType.BREED_TARGET, MemoryStatus.VALUE_ABSENT),
Pair.of(
MemoryModuleType.LONG_JUMP_COOLDOWN_TICKS, MemoryStatus.VALUE_ABSENT
),
Pair.of(WBMemoryModules.IS_IN_WATER.get(), MemoryStatus.VALUE_ABSENT)
)
);
}
private static void addTongueActivities(Brain<Frog> brain) {
brain.addActivityAndRemoveMemoryWhenStopped(WBActivities.TONGUE.get(), 0, ImmutableList.of(new StopAttackingIfTargetInvalid<>(), new FrogEat(WBSoundEvents.FROG_TONGUE, WBSoundEvents.FROG_EAT)), MemoryModuleType.ATTACK_TARGET);
brain.addActivityAndRemoveMemoryWhenStopped(
WBActivities.TONGUE.get(),
0,
ImmutableList.of(
new StopAttackingIfTargetInvalid<>(),
new FrogEat(WBSoundEvents.FROG_TONGUE, WBSoundEvents.FROG_EAT)
),
MemoryModuleType.ATTACK_TARGET
);
}
private static boolean isNotBreeding(Frog frog) {
@ -96,7 +272,13 @@ public class FrogBrain {
}
public static void updateActivities(Frog frog) {
frog.getBrain().setActiveActivityToFirstValid(ImmutableList.of(WBActivities.TONGUE.get(), WBActivities.LAY_SPAWN.get(), Activity.LONG_JUMP, WBActivities.SWIM.get(), Activity.IDLE));
frog.getBrain().setActiveActivityToFirstValid(ImmutableList.of(
WBActivities.TONGUE.get(),
WBActivities.LAY_SPAWN.get(),
Activity.LONG_JUMP,
WBActivities.SWIM.get(),
Activity.IDLE
));
}
public static Ingredient getTemptItems() {

View file

@ -38,11 +38,52 @@ public class TadpoleBrain {
}
private static void addCoreActivities(Brain<Tadpole> brain) {
brain.addActivity(Activity.CORE, 0, ImmutableList.of(new AnimalPanic(2.0f), new LookAtTargetSink(45, 90), new MoveToTargetSink(), new CountDownCooldownTicks(MemoryModuleType.TEMPTATION_COOLDOWN_TICKS)));
brain.addActivity(
Activity.CORE,
0,
ImmutableList.of(
new AnimalPanic(2.0f),
new LookAtTargetSink(45, 90),
new MoveToTargetSink(),
new CountDownCooldownTicks(MemoryModuleType.TEMPTATION_COOLDOWN_TICKS)
)
);
}
private static void addIdleActivities(Brain<Tadpole> brain) {
brain.addActivity(Activity.IDLE, ImmutableList.of(Pair.of(0, new RunSometimes<LivingEntity>(new SetEntityLookTarget(EntityType.PLAYER, 6.0f), UniformInt.of(30, 60))), Pair.of(3, new TryFindWater(6, 0.15f)), Pair.of(4, new GateBehavior<>(ImmutableMap.of(MemoryModuleType.WALK_TARGET, MemoryStatus.VALUE_ABSENT), ImmutableSet.of(), GateBehavior.OrderPolicy.ORDERED, GateBehavior.RunningPolicy.TRY_ALL, ImmutableList.of(Pair.of(new RandomSwim(0.5F), 2), Pair.of(new RandomStroll(0.15F), 2), Pair.of(new SetWalkTargetFromLookTarget(0.5f, 3), 3), Pair.of(new RunIf<>(Entity::isInWaterOrBubble, new DoNothing(30, 60)), 5))))));
brain.addActivity(
Activity.IDLE,
ImmutableList.of(
Pair.of(
0,
new RunSometimes<LivingEntity>(
new SetEntityLookTarget(EntityType.PLAYER, 6.0f),
UniformInt.of(30, 60)
)
),
Pair.of(3, new TryFindWater(6, 0.15f)),
Pair.of(
4,
new GateBehavior<>(
ImmutableMap
.of(MemoryModuleType.WALK_TARGET, MemoryStatus.VALUE_ABSENT),
ImmutableSet.of(),
GateBehavior.OrderPolicy.ORDERED,
GateBehavior.RunningPolicy.TRY_ALL,
ImmutableList.of(
Pair.of(new RandomSwim(0.5F), 2),
Pair.of(new RandomStroll(0.15F), 2),
Pair.of(new SetWalkTargetFromLookTarget(0.5f, 3), 3),
Pair
.of(new RunIf<>(
Entity::isInWaterOrBubble, new DoNothing(30, 60)
),
5)
)
)
)
)
);
}
public static void updateActivities(Tadpole tadpole) {

View file

@ -1,13 +1,15 @@
package com.cursedcauldron.wildbackport.common.entities.brain;
import java.util.List;
import com.cursedcauldron.wildbackport.common.entities.Warden;
import com.cursedcauldron.wildbackport.common.entities.brain.warden.Digging;
import com.cursedcauldron.wildbackport.common.entities.brain.warden.Dismount;
import com.cursedcauldron.wildbackport.common.entities.brain.warden.Emerging;
import com.cursedcauldron.wildbackport.common.entities.brain.warden.FindRoarTarget;
import com.cursedcauldron.wildbackport.common.entities.brain.warden.ForgetAttackTarget;
import com.cursedcauldron.wildbackport.common.entities.brain.warden.GoToTargetLocation;
import com.cursedcauldron.wildbackport.common.entities.brain.warden.Roar;
import com.cursedcauldron.wildbackport.common.entities.brain.warden.FindRoarTarget;
import com.cursedcauldron.wildbackport.common.entities.brain.warden.SetWardenLookTarget;
import com.cursedcauldron.wildbackport.common.entities.brain.warden.Sniffing;
import com.cursedcauldron.wildbackport.common.entities.brain.warden.SonicBoom;
@ -44,8 +46,6 @@ import net.minecraft.world.entity.ai.sensing.Sensor;
import net.minecraft.world.entity.ai.sensing.SensorType;
import net.minecraft.world.entity.schedule.Activity;
import java.util.List;
//<>
public class WardenBrain {
@ -53,16 +53,55 @@ public class WardenBrain {
public static final int EMERGE_DURATION = Mth.ceil(133.59999F);
public static final int ROAR_DURATION = Mth.ceil(84.0F);
private static final int SNIFFING_DURATION = Mth.ceil(83.2F);
private static final List<SensorType<? extends Sensor<? super Warden>>> SENSOR_TYPES = List.of(SensorType.NEAREST_PLAYERS, WBSensorTypes.WARDEN_ENTITY_SENSOR.get());
private static final List<MemoryModuleType<?>> MEMORY_TYPES = List.of(MemoryModuleType.NEAREST_LIVING_ENTITIES, MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES, MemoryModuleType.NEAREST_VISIBLE_PLAYER, MemoryModuleType.NEAREST_VISIBLE_ATTACKABLE_PLAYER, MemoryModuleType.NEAREST_VISIBLE_NEMESIS, MemoryModuleType.LOOK_TARGET, MemoryModuleType.WALK_TARGET, MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE, MemoryModuleType.PATH, MemoryModuleType.ATTACK_TARGET, MemoryModuleType.ATTACK_COOLING_DOWN, MemoryModuleType.NEAREST_ATTACKABLE, WBMemoryModules.ROAR_TARGET.get(), WBMemoryModules.DISTURBANCE_LOCATION.get(), WBMemoryModules.RECENT_PROJECTILE.get(), WBMemoryModules.IS_SNIFFING.get(), WBMemoryModules.IS_EMERGING.get(), WBMemoryModules.ROAR_SOUND_DELAY.get(), WBMemoryModules.DIG_COOLDOWN.get(), WBMemoryModules.ROAR_SOUND_COOLDOWN.get(), WBMemoryModules.SNIFF_COOLDOWN.get(), WBMemoryModules.TOUCH_COOLDOWN.get(), WBMemoryModules.VIBRATION_COOLDOWN.get(), WBMemoryModules.SONIC_BOOM_COOLDOWN.get(), WBMemoryModules.SONIC_BOOM_SOUND_COOLDOWN.get(), WBMemoryModules.SONIC_BOOM_SOUND_DELAY.get());
private static final Behavior<Warden> DIG_COOLDOWN_SETTER = new Behavior<>(ImmutableMap.of(WBMemoryModules.DIG_COOLDOWN.get(), MemoryStatus.REGISTERED)) {
@Override protected void start(ServerLevel level, Warden warden, long time) {
private static final List<SensorType<? extends Sensor<? super Warden>>> SENSOR_TYPES
= List.of(SensorType.NEAREST_PLAYERS, WBSensorTypes.WARDEN_ENTITY_SENSOR.get());
private static final List<MemoryModuleType<?>> MEMORY_TYPES = List.of(
MemoryModuleType.NEAREST_LIVING_ENTITIES,
MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES,
MemoryModuleType.NEAREST_VISIBLE_PLAYER,
MemoryModuleType.NEAREST_VISIBLE_ATTACKABLE_PLAYER,
MemoryModuleType.NEAREST_VISIBLE_NEMESIS,
MemoryModuleType.LOOK_TARGET,
MemoryModuleType.WALK_TARGET,
MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE,
MemoryModuleType.PATH,
MemoryModuleType.ATTACK_TARGET,
MemoryModuleType.ATTACK_COOLING_DOWN,
MemoryModuleType.NEAREST_ATTACKABLE,
WBMemoryModules.ROAR_TARGET.get(),
WBMemoryModules.DISTURBANCE_LOCATION.get(),
WBMemoryModules.RECENT_PROJECTILE.get(),
WBMemoryModules.IS_SNIFFING.get(),
WBMemoryModules.IS_EMERGING.get(),
WBMemoryModules.ROAR_SOUND_DELAY.get(),
WBMemoryModules.DIG_COOLDOWN.get(),
WBMemoryModules.ROAR_SOUND_COOLDOWN.get(),
WBMemoryModules.SNIFF_COOLDOWN.get(),
WBMemoryModules.TOUCH_COOLDOWN.get(),
WBMemoryModules.VIBRATION_COOLDOWN.get(),
WBMemoryModules.SONIC_BOOM_COOLDOWN.get(),
WBMemoryModules.SONIC_BOOM_SOUND_COOLDOWN.get(),
WBMemoryModules.SONIC_BOOM_SOUND_DELAY.get()
);
private static final Behavior<Warden> DIG_COOLDOWN_SETTER = new Behavior<>(
ImmutableMap.of(WBMemoryModules.DIG_COOLDOWN.get(), MemoryStatus.REGISTERED)
) {
@Override
protected void start(ServerLevel level, Warden warden, long time) {
resetDigCooldown(warden);
}
};
public static void updateActivities(Warden warden) {
warden.getBrain().setActiveActivityToFirstValid(ImmutableList.of(WBActivities.EMERGE.get(), WBActivities.DIG.get(), WBActivities.ROAR.get(), Activity.FIGHT, WBActivities.INVESTIGATE.get(), WBActivities.SNIFF.get(), Activity.IDLE));
warden.getBrain().setActiveActivityToFirstValid(ImmutableList.of(
WBActivities.EMERGE.get(),
WBActivities.DIG.get(),
WBActivities.ROAR.get(),
Activity.FIGHT,
WBActivities.INVESTIGATE.get(),
WBActivities.SNIFF.get(),
Activity.IDLE
));
}
public static Brain<?> makeBrain(Warden warden, Dynamic<?> dynamic) {
@ -83,58 +122,155 @@ public class WardenBrain {
}
private static void initCoreActivity(Brain<Warden> brain) {
brain.addActivity(Activity.CORE, 0, ImmutableList.of(new Swim(0.8F), new SetWardenLookTarget(), new LookAtTargetSink(45, 90), new MoveToTargetSink()));
brain.addActivity(
Activity.CORE,
0,
ImmutableList.of(
new Swim(0.8F),
new SetWardenLookTarget(),
new LookAtTargetSink(45, 90),
new MoveToTargetSink()
)
);
}
private static void initEmergeActivity(Brain<Warden> brain) {
brain.addActivityAndRemoveMemoryWhenStopped(WBActivities.EMERGE.get(), 5, ImmutableList.of(new Emerging<>(EMERGE_DURATION)), WBMemoryModules.IS_EMERGING.get());
brain.addActivityAndRemoveMemoryWhenStopped(
WBActivities.EMERGE.get(),
5,
ImmutableList.of(new Emerging<>(EMERGE_DURATION)),
WBMemoryModules.IS_EMERGING.get()
);
}
private static void initDiggingActivity(Brain<Warden> brain) {
brain.addActivityWithConditions(WBActivities.DIG.get(), ImmutableList.of(Pair.of(0, new Dismount()), Pair.of(1, new Digging<>(DIGGING_DURATION))), ImmutableSet.of(Pair.of(WBMemoryModules.ROAR_TARGET.get(), MemoryStatus.VALUE_ABSENT), Pair.of(WBMemoryModules.DIG_COOLDOWN.get(), MemoryStatus.VALUE_ABSENT)));
brain.addActivityWithConditions(
WBActivities.DIG.get(),
ImmutableList.of(
Pair.of(0, new Dismount()), Pair.of(1, new Digging<>(DIGGING_DURATION))
),
ImmutableSet.of(
Pair.of(WBMemoryModules.ROAR_TARGET.get(), MemoryStatus.VALUE_ABSENT),
Pair.of(WBMemoryModules.DIG_COOLDOWN.get(), MemoryStatus.VALUE_ABSENT)
)
);
}
private static void initIdleActivity(Brain<Warden> brain) {
brain.addActivity(Activity.IDLE, 10, ImmutableList.of(new FindRoarTarget<>(Warden::getPrimeSuspect), new TryToSniff(), new RunOne<>(ImmutableMap.of(WBMemoryModules.IS_SNIFFING.get(), MemoryStatus.VALUE_ABSENT), ImmutableList.of(Pair.of(new RandomStroll(0.5F), 2), Pair.of(new DoNothing(30, 60), 1)))));
brain.addActivity(
Activity.IDLE,
10,
ImmutableList.of(
new FindRoarTarget<>(Warden::getPrimeSuspect),
new TryToSniff(),
new RunOne<>(
ImmutableMap.of(
WBMemoryModules.IS_SNIFFING.get(), MemoryStatus.VALUE_ABSENT
),
ImmutableList.of(
Pair.of(new RandomStroll(0.5F), 2),
Pair.of(new DoNothing(30, 60), 1)
)
)
)
);
}
private static void initInvestigateActivity(Brain<Warden> brain) {
brain.addActivityAndRemoveMemoryWhenStopped(WBActivities.INVESTIGATE.get(), 5, ImmutableList.of(new FindRoarTarget<>(Warden::getPrimeSuspect), new GoToTargetLocation<>(WBMemoryModules.DISTURBANCE_LOCATION.get(), 2, 0.7F)), WBMemoryModules.DISTURBANCE_LOCATION.get());
brain.addActivityAndRemoveMemoryWhenStopped(
WBActivities.INVESTIGATE.get(),
5,
ImmutableList.of(
new FindRoarTarget<>(Warden::getPrimeSuspect),
new GoToTargetLocation<>(
WBMemoryModules.DISTURBANCE_LOCATION.get(), 2, 0.7F
)
),
WBMemoryModules.DISTURBANCE_LOCATION.get()
);
}
private static void initSniffingActivity(Brain<Warden> brain) {
brain.addActivityAndRemoveMemoryWhenStopped(WBActivities.SNIFF.get(), 5, ImmutableList.of(new FindRoarTarget<>(Warden::getPrimeSuspect), new Sniffing<>(SNIFFING_DURATION)), WBMemoryModules.IS_SNIFFING.get());
brain.addActivityAndRemoveMemoryWhenStopped(
WBActivities.SNIFF.get(),
5,
ImmutableList.of(
new FindRoarTarget<>(Warden::getPrimeSuspect),
new Sniffing<>(SNIFFING_DURATION)
),
WBMemoryModules.IS_SNIFFING.get()
);
}
private static void initRoarActivity(Brain<Warden> brain) {
brain.addActivityAndRemoveMemoryWhenStopped(WBActivities.ROAR.get(), 10, ImmutableList.of(new Roar()), WBMemoryModules.ROAR_TARGET.get());
brain.addActivityAndRemoveMemoryWhenStopped(
WBActivities.ROAR.get(),
10,
ImmutableList.of(new Roar()),
WBMemoryModules.ROAR_TARGET.get()
);
}
private static void initFightActivity(Warden warden, Brain<Warden> brain) {
brain.addActivityAndRemoveMemoryWhenStopped(Activity.FIGHT, 10, ImmutableList.of(DIG_COOLDOWN_SETTER, new ForgetAttackTarget<>(entity -> !warden.getAngriness().isAngry() || !warden.isValidTarget(entity), WardenBrain::removeDeadSuspect, false), new SetEntityLookTarget(entity -> isTargeting(warden, entity), (float)warden.getAttributeValue(Attributes.FOLLOW_RANGE)), new SetWalkTargetFromAttackTargetIfTargetOutOfReach(1.2F), new SonicBoom(), new MeleeAttack(18)), MemoryModuleType.ATTACK_TARGET);
brain.addActivityAndRemoveMemoryWhenStopped(
Activity.FIGHT,
10,
ImmutableList.of(
DIG_COOLDOWN_SETTER,
new ForgetAttackTarget<>(
entity
-> !warden.getAngriness().isAngry() || !warden.isValidTarget(entity),
WardenBrain::removeDeadSuspect,
false
),
new SetEntityLookTarget(
entity
-> isTargeting(warden, entity),
(float) warden.getAttributeValue(Attributes.FOLLOW_RANGE)
),
new SetWalkTargetFromAttackTargetIfTargetOutOfReach(1.2F),
new SonicBoom(),
new MeleeAttack(18)
),
MemoryModuleType.ATTACK_TARGET
);
}
private static boolean isTargeting(Warden warden, LivingEntity entity) {
return warden.getBrain().getMemory(MemoryModuleType.ATTACK_TARGET).filter(target -> target == entity).isPresent();
return warden.getBrain()
.getMemory(MemoryModuleType.ATTACK_TARGET)
.filter(target -> target == entity)
.isPresent();
}
private static void removeDeadSuspect(Warden warden, LivingEntity suspect) {
if (!warden.isValidTarget(suspect)) warden.removeSuspect(suspect);
if (!warden.isValidTarget(suspect))
warden.removeSuspect(suspect);
resetDigCooldown(warden);
}
public static void resetDigCooldown(LivingEntity warden) {
if (warden.getBrain().hasMemoryValue(WBMemoryModules.DIG_COOLDOWN.get())) {
warden.getBrain().setMemoryWithExpiry(WBMemoryModules.DIG_COOLDOWN.get(), Unit.INSTANCE, 1200L);
warden.getBrain().setMemoryWithExpiry(
WBMemoryModules.DIG_COOLDOWN.get(), Unit.INSTANCE, 1200L
);
}
}
public static void lookAtDisturbance(Warden warden, BlockPos pos) {
if (warden.level.getWorldBorder().isWithinBounds(pos) && warden.getPrimeSuspect().isEmpty() && warden.getBrain().getMemory(MemoryModuleType.ATTACK_TARGET).isEmpty()) {
if (warden.level.getWorldBorder().isWithinBounds(pos)
&& warden.getPrimeSuspect().isEmpty()
&& warden.getBrain().getMemory(MemoryModuleType.ATTACK_TARGET).isEmpty()) {
resetDigCooldown(warden);
warden.getBrain().setMemoryWithExpiry(WBMemoryModules.SNIFF_COOLDOWN.get(), Unit.INSTANCE, 100L);
warden.getBrain().setMemoryWithExpiry(MemoryModuleType.LOOK_TARGET, new BlockPosTracker(pos), 100L);
warden.getBrain().setMemoryWithExpiry(WBMemoryModules.DISTURBANCE_LOCATION.get(), pos, 100L);
warden.getBrain().setMemoryWithExpiry(
WBMemoryModules.SNIFF_COOLDOWN.get(), Unit.INSTANCE, 100L
);
warden.getBrain().setMemoryWithExpiry(
MemoryModuleType.LOOK_TARGET, new BlockPosTracker(pos), 100L
);
warden.getBrain().setMemoryWithExpiry(
WBMemoryModules.DISTURBANCE_LOCATION.get(), pos, 100L
);
warden.getBrain().eraseMemory(MemoryModuleType.WALK_TARGET);
}
}

View file

@ -11,9 +11,18 @@ public class FlyingRandomStroll extends RandomStroll {
super(distance, true);
}
@Override @Nullable
@Override
@Nullable
protected Vec3 getTargetPos(PathfinderMob mob) {
Vec3 vector = mob.getViewVector(0.0F);
return AirAndWaterRandomPos.getPos(mob, this.maxHorizontalDistance, this.maxVerticalDistance, -2, vector.x, vector.z, (float)Math.PI / 2.0F);
return AirAndWaterRandomPos.getPos(
mob,
this.maxHorizontalDistance,
this.maxVerticalDistance,
-2,
vector.x,
vector.z,
(float) Math.PI / 2.0F
);
}
}

View file

@ -1,5 +1,8 @@
package com.cursedcauldron.wildbackport.common.entities.brain.allay;
import java.util.Optional;
import java.util.function.Function;
import com.cursedcauldron.wildbackport.client.registry.WBSoundEvents;
import com.cursedcauldron.wildbackport.common.entities.Allay;
import com.cursedcauldron.wildbackport.common.entities.brain.AllayBrain;
@ -21,17 +24,24 @@ import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import net.minecraft.world.phys.Vec3;
import java.util.Optional;
import java.util.function.Function;
//<>
public class GiveInventoryToLookTarget<E extends LivingEntity & InventoryCarrier> extends Behavior<E> {
public class GiveInventoryToLookTarget<E extends LivingEntity & InventoryCarrier>
extends Behavior<E> {
private final Function<LivingEntity, Optional<PositionTracker>> lookTarget;
private final float speed;
public GiveInventoryToLookTarget(Function<LivingEntity, Optional<PositionTracker>> lookTarget, float speed) {
super(ImmutableMap.of(MemoryModuleType.LOOK_TARGET, MemoryStatus.REGISTERED, MemoryModuleType.WALK_TARGET, MemoryStatus.REGISTERED, WBMemoryModules.ITEM_PICKUP_COOLDOWN_TICKS.get(), MemoryStatus.REGISTERED));
public GiveInventoryToLookTarget(
Function<LivingEntity, Optional<PositionTracker>> lookTarget, float speed
) {
super(ImmutableMap.of(
MemoryModuleType.LOOK_TARGET,
MemoryStatus.REGISTERED,
MemoryModuleType.WALK_TARGET,
MemoryStatus.REGISTERED,
WBMemoryModules.ITEM_PICKUP_COOLDOWN_TICKS.get(),
MemoryStatus.REGISTERED
));
this.lookTarget = lookTarget;
this.speed = speed;
}
@ -48,7 +58,9 @@ public class GiveInventoryToLookTarget<E extends LivingEntity & InventoryCarrier
@Override
protected void start(ServerLevel level, E entity, long time) {
this.lookTarget.apply(entity).ifPresent(target -> MobUtils.walkTowards(entity, target, this.speed, 3));
this.lookTarget.apply(entity).ifPresent(
target -> MobUtils.walkTowards(entity, target, this.speed, 3)
);
}
@Override
@ -56,28 +68,35 @@ public class GiveInventoryToLookTarget<E extends LivingEntity & InventoryCarrier
Optional<PositionTracker> lookTarget = this.lookTarget.apply(entity);
if (lookTarget.isPresent()) {
PositionTracker target = lookTarget.get();
double distance = target.currentPosition().distanceTo(entity.getEyePosition());
double distance
= target.currentPosition().distanceTo(entity.getEyePosition());
if (distance < 3.0D) {
ItemStack stack = entity.getInventory().removeItem(0, 1);
if (!stack.isEmpty()) {
playThrowSound(entity, stack, offsetTarget(target));
if (entity instanceof Allay allay) {
AllayBrain.getLikedPlayer(allay).ifPresent(player -> this.triggerCriteria(target, stack, player));
AllayBrain.getLikedPlayer(allay).ifPresent(
player -> this.triggerCriteria(target, stack, player)
);
}
entity.getBrain().setMemory(WBMemoryModules.ITEM_PICKUP_COOLDOWN_TICKS.get(), 60);
entity.getBrain().setMemory(
WBMemoryModules.ITEM_PICKUP_COOLDOWN_TICKS.get(), 60
);
}
}
}
}
private void triggerCriteria(PositionTracker target, ItemStack stack, ServerPlayer player) {
private void
triggerCriteria(PositionTracker target, ItemStack stack, ServerPlayer player) {
BlockPos pos = target.currentBlockPosition().below();
// WBCriteriaTriggers.ALLAY_DROP_ITEM_ON_BLOCK.trigger(player, pos, stack);
// WBCriteriaTriggers.ALLAY_DROP_ITEM_ON_BLOCK.trigger(player, pos, stack);
}
private boolean hasItemAndTarget(E entity) {
return !entity.getInventory().isEmpty() && this.lookTarget.apply(entity).isPresent();
return !entity.getInventory().isEmpty()
&& this.lookTarget.apply(entity).isPresent();
}
private static Vec3 offsetTarget(PositionTracker tracker) {
@ -90,7 +109,14 @@ public class GiveInventoryToLookTarget<E extends LivingEntity & InventoryCarrier
Level level = entity.level;
if (level.getGameTime() % 7L == 0L && level.random.nextDouble() < 0.9D) {
float pitch = Util.getRandom(Allay.THROW_SOUND_PITCHES, level.getRandom());
level.playSound(null, entity, WBSoundEvents.ALLAY_ITEM_THROW, SoundSource.NEUTRAL, 1.0F, pitch);
level.playSound(
null,
entity,
WBSoundEvents.ALLAY_ITEM_THROW,
SoundSource.NEUTRAL,
1.0F,
pitch
);
}
}
}

View file

@ -1,5 +1,8 @@
package com.cursedcauldron.wildbackport.common.entities.brain.allay;
import java.util.Optional;
import java.util.function.Function;
import com.cursedcauldron.wildbackport.common.utils.MobUtils;
import com.google.common.collect.ImmutableMap;
import net.minecraft.server.level.ServerLevel;
@ -9,16 +12,18 @@ import net.minecraft.world.entity.ai.behavior.PositionTracker;
import net.minecraft.world.entity.ai.memory.MemoryModuleType;
import net.minecraft.world.entity.ai.memory.MemoryStatus;
import java.util.Optional;
import java.util.function.Function;
public class StayCloseToTarget<E extends LivingEntity> extends Behavior<E> {
private final Function<LivingEntity, Optional<PositionTracker>> lookTarget;
private final int completitionRange;
private final int searchRange;
private final float speed;
public StayCloseToTarget(Function<LivingEntity, Optional<PositionTracker>> lookTarget, int completitionRange, int searchRange, float speed) {
public StayCloseToTarget(
Function<LivingEntity, Optional<PositionTracker>> lookTarget,
int completitionRange,
int searchRange,
float speed
) {
super(ImmutableMap.of(MemoryModuleType.WALK_TARGET, MemoryStatus.VALUE_ABSENT));
this.lookTarget = lookTarget;
this.completitionRange = completitionRange;
@ -29,11 +34,19 @@ public class StayCloseToTarget<E extends LivingEntity> extends Behavior<E> {
@Override
protected boolean checkExtraStartConditions(ServerLevel level, E entity) {
Optional<PositionTracker> tracker = this.lookTarget.apply(entity);
return tracker.isPresent() && !entity.position().closerThan(tracker.get().currentPosition(), this.searchRange);
return tracker.isPresent()
&& !entity.position().closerThan(
tracker.get().currentPosition(), this.searchRange
);
}
@Override
protected void start(ServerLevel level, E entity, long time) {
MobUtils.walkTowards(entity, this.lookTarget.apply(entity).get(), this.speed, this.completitionRange);
MobUtils.walkTowards(
entity,
this.lookTarget.apply(entity).get(),
this.speed,
this.completitionRange
);
}
}

View file

@ -1,5 +1,11 @@
package com.cursedcauldron.wildbackport.common.entities.brain.frog;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.function.Function;
import java.util.function.Predicate;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.server.level.ServerLevel;
@ -10,19 +16,22 @@ import net.minecraft.world.entity.Mob;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.function.Function;
import java.util.function.Predicate;
public class BiasedLongJumpTask<E extends Mob> extends FrogJumpToRandomPos<E> {
private final TagKey<Block> preferredBlocks;
private final float chance;
private final List<FrogJumpToRandomPos.Target> targetCandidates = new ArrayList<>();
private boolean priorityOnPreferred;
public BiasedLongJumpTask(UniformInt cooldown, int yRange, int xzRange, float range, Function<E, SoundEvent> landingSound, TagKey<Block> preferredBlocks, float chance, Predicate<BlockState> landingBlocks) {
public BiasedLongJumpTask(
UniformInt cooldown,
int yRange,
int xzRange,
float range,
Function<E, SoundEvent> landingSound,
TagKey<Block> preferredBlocks,
float chance,
Predicate<BlockState> landingBlocks
) {
super(cooldown, yRange, xzRange, range, landingSound, landingBlocks);
this.preferredBlocks = preferredBlocks;
this.chance = chance;
@ -46,7 +55,11 @@ public class BiasedLongJumpTask<E extends Mob> extends FrogJumpToRandomPos<E> {
Optional<FrogJumpToRandomPos.Target> jumpTarget = super.jumpTarget(level);
if (jumpTarget.isPresent()) {
FrogJumpToRandomPos.Target target = jumpTarget.get();
if (level.getBlockState(mutable.setWithOffset(target.getPos(), Direction.DOWN)).is(this.preferredBlocks)) {
if (level
.getBlockState(
mutable.setWithOffset(target.getPos(), Direction.DOWN)
)
.is(this.preferredBlocks)) {
return jumpTarget;
}
@ -54,7 +67,9 @@ public class BiasedLongJumpTask<E extends Mob> extends FrogJumpToRandomPos<E> {
}
}
return !this.targetCandidates.isEmpty() ? Optional.of(this.targetCandidates.remove(0)) : Optional.empty();
return !this.targetCandidates.isEmpty()
? Optional.of(this.targetCandidates.remove(0))
: Optional.empty();
}
}
@ -64,6 +79,7 @@ public class BiasedLongJumpTask<E extends Mob> extends FrogJumpToRandomPos<E> {
}
private boolean cantLandInFluid(ServerLevel level, BlockPos pos) {
return level.getFluidState(pos).isEmpty() && level.getFluidState(pos.below()).isEmpty();
return level.getFluidState(pos).isEmpty()
&& level.getFluidState(pos.below()).isEmpty();
}
}

View file

@ -13,7 +13,9 @@ public class Croak extends Behavior<Frog> {
private int ticks;
public Croak() {
super(ImmutableMap.of(MemoryModuleType.WALK_TARGET, MemoryStatus.VALUE_ABSENT), 100);
super(
ImmutableMap.of(MemoryModuleType.WALK_TARGET, MemoryStatus.VALUE_ABSENT), 100
);
}
@Override
@ -28,7 +30,6 @@ public class Croak extends Behavior<Frog> {
@Override
protected void start(ServerLevel level, Frog frog, long time) {
if (!frog.isInWaterOrBubble() && !frog.isInLava()) {
frog.setPose(Poses.CROAKING.get());
this.ticks = 0;

View file

@ -1,5 +1,9 @@
package com.cursedcauldron.wildbackport.common.entities.brain.frog;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import com.cursedcauldron.wildbackport.common.entities.Frog;
import com.cursedcauldron.wildbackport.common.registry.entity.WBMemoryModules;
import net.minecraft.world.entity.LivingEntity;
@ -7,20 +11,21 @@ import net.minecraft.world.entity.ai.memory.MemoryModuleType;
import net.minecraft.world.entity.ai.sensing.NearestVisibleLivingEntitySensor;
import net.minecraft.world.entity.ai.sensing.Sensor;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
//<>
public class FrogAttackablesSensor extends NearestVisibleLivingEntitySensor {
@Override
protected boolean isMatchingEntity(LivingEntity entity, LivingEntity target) {
return !entity.getBrain().hasMemoryValue(MemoryModuleType.HAS_HUNTING_COOLDOWN) && Sensor.isEntityAttackable(entity, target) && Frog.isValidFrogFood(target) && !this.cantReachTarget(entity, target) && target.closerThan(entity, 10.0D);
return !entity.getBrain().hasMemoryValue(MemoryModuleType.HAS_HUNTING_COOLDOWN)
&& Sensor.isEntityAttackable(entity, target) && Frog.isValidFrogFood(target)
&& !this.cantReachTarget(entity, target) && target.closerThan(entity, 10.0D);
}
private boolean cantReachTarget(LivingEntity entity, LivingEntity target) {
List<UUID> targets = entity.getBrain().getMemory(WBMemoryModules.UNREACHABLE_TONGUE_TARGETS.get()).orElseGet(ArrayList::new);
List<UUID> targets
= entity.getBrain()
.getMemory(WBMemoryModules.UNREACHABLE_TONGUE_TARGETS.get())
.orElseGet(ArrayList::new);
return targets.contains(target.getUUID());
}

View file

@ -1,5 +1,10 @@
package com.cursedcauldron.wildbackport.common.entities.brain.frog;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
import com.cursedcauldron.wildbackport.common.entities.Frog;
import com.cursedcauldron.wildbackport.common.entities.access.api.Poses;
import com.cursedcauldron.wildbackport.common.registry.WBBlocks;
@ -21,11 +26,6 @@ import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.level.pathfinder.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
//<>
public class FrogEat extends Behavior<Frog> {
@ -36,34 +36,50 @@ public class FrogEat extends Behavior<Frog> {
private Phase phase = Phase.DONE;
public FrogEat(SoundEvent tongueSound, SoundEvent eatSound) {
super(ImmutableMap.of(MemoryModuleType.WALK_TARGET, MemoryStatus.VALUE_ABSENT, MemoryModuleType.LOOK_TARGET, MemoryStatus.REGISTERED, MemoryModuleType.ATTACK_TARGET, MemoryStatus.VALUE_PRESENT), 100);
super(
ImmutableMap.of(
MemoryModuleType.WALK_TARGET,
MemoryStatus.VALUE_ABSENT,
MemoryModuleType.LOOK_TARGET,
MemoryStatus.REGISTERED,
MemoryModuleType.ATTACK_TARGET,
MemoryStatus.VALUE_PRESENT
),
100
);
this.tongueSound = tongueSound;
this.eatSound = eatSound;
}
@Override
protected boolean checkExtraStartConditions(ServerLevel level, Frog frog) {
LivingEntity target = frog.getBrain().getMemory(MemoryModuleType.ATTACK_TARGET).get();
LivingEntity target
= frog.getBrain().getMemory(MemoryModuleType.ATTACK_TARGET).get();
boolean flag = this.canMoveToTarget(frog, target);
if (!flag) {
frog.getBrain().eraseMemory(MemoryModuleType.ATTACK_TARGET);
this.cantReachTarget(frog, target);
}
return flag && frog.getPose() != Poses.CROAKING.get() && Frog.isValidFrogFood(target);
return flag && frog.getPose() != Poses.CROAKING.get()
&& Frog.isValidFrogFood(target);
}
@Override
protected boolean canStillUse(ServerLevel level, Frog frog, long time) {
return frog.getBrain().hasMemoryValue(MemoryModuleType.ATTACK_TARGET) && this.phase != Phase.DONE;
return frog.getBrain().hasMemoryValue(MemoryModuleType.ATTACK_TARGET)
&& this.phase != Phase.DONE;
}
@Override
protected void start(ServerLevel level, Frog frog, long time) {
LivingEntity entity = frog.getBrain().getMemory(MemoryModuleType.ATTACK_TARGET).get();
LivingEntity entity
= frog.getBrain().getMemory(MemoryModuleType.ATTACK_TARGET).get();
BehaviorUtils.lookAtEntity(frog, entity);
frog.setFrogTarget(entity);
frog.getBrain().setMemory(MemoryModuleType.WALK_TARGET, new WalkTarget(entity.position(), 2.0F, 0));
frog.getBrain().setMemory(
MemoryModuleType.WALK_TARGET, new WalkTarget(entity.position(), 2.0F, 0)
);
this.moveToTargetTick = 10;
this.phase = Phase.MOVE_TO_TARGET;
}
@ -109,54 +125,64 @@ public class FrogEat extends Behavior<Frog> {
frog.setFrogTarget(target);
switch (this.phase) {
case MOVE_TO_TARGET:
if (target.distanceTo(frog) < 1.75F) {
level.playSound(null, frog, this.tongueSound, SoundSource.NEUTRAL, 2.0F, 1.0F);
frog.setPose(Poses.USING_TONGUE.get());
target.setDeltaMovement(target.position().vectorTo(frog.position()).normalize().scale(0.75D));
this.eatTick = 0;
this.phase = Phase.CATCH_ANIMATION;
} else if (this.moveToTargetTick <= 0) {
frog.getBrain().setMemory(MemoryModuleType.WALK_TARGET, new WalkTarget(target.position(), 2.0F, 0));
this.moveToTargetTick = 10;
} else {
--this.moveToTargetTick;
}
break;
case CATCH_ANIMATION:
if (this.eatTick++ >= 6) {
this.phase = Phase.EAT_ANIMATION;
this.eat(level, frog);
}
break;
case EAT_ANIMATION:
if (this.eatTick >= 10) {
this.phase = Phase.DONE;
} else {
++this.eatTick;
}
case DONE:
if (target.distanceTo(frog) < 1.75F) {
level.playSound(
null, frog, this.tongueSound, SoundSource.NEUTRAL, 2.0F, 1.0F
);
frog.setPose(Poses.USING_TONGUE.get());
target.setDeltaMovement(target.position()
.vectorTo(frog.position())
.normalize()
.scale(0.75D));
this.eatTick = 0;
this.phase = Phase.CATCH_ANIMATION;
} else if (this.moveToTargetTick <= 0) {
frog.getBrain().setMemory(
MemoryModuleType.WALK_TARGET,
new WalkTarget(target.position(), 2.0F, 0)
);
this.moveToTargetTick = 10;
} else {
--this.moveToTargetTick;
}
break;
case CATCH_ANIMATION:
if (this.eatTick++ >= 6) {
this.phase = Phase.EAT_ANIMATION;
this.eat(level, frog);
}
break;
case EAT_ANIMATION:
if (this.eatTick >= 10) {
this.phase = Phase.DONE;
} else {
++this.eatTick;
}
case DONE:
}
}
}
private boolean canMoveToTarget(Frog frog, LivingEntity entity) {
Path path = frog.getNavigation().createPath(entity, 0);
return path != null && path.getDistToTarget() < 1.75F;
}
private boolean canMoveToTarget(Frog frog, LivingEntity entity) {
Path path = frog.getNavigation().createPath(entity, 0);
return path != null && path.getDistToTarget() < 1.75F;
}
private void cantReachTarget(Frog frog, LivingEntity entity) {
List<UUID> targets = frog.getBrain().getMemory(WBMemoryModules.UNREACHABLE_TONGUE_TARGETS.get()).orElseGet(ArrayList::new);
boolean notTargeting = !targets.contains(entity.getUUID());
if (targets.size() == 5 && notTargeting) targets.remove(0);
private void cantReachTarget(Frog frog, LivingEntity entity) {
List<UUID> targets
= frog.getBrain()
.getMemory(WBMemoryModules.UNREACHABLE_TONGUE_TARGETS.get())
.orElseGet(ArrayList::new);
boolean notTargeting = !targets.contains(entity.getUUID());
if (targets.size() == 5 && notTargeting)
targets.remove(0);
if (notTargeting) targets.add(entity.getUUID());
if (notTargeting)
targets.add(entity.getUUID());
frog.getBrain().setMemoryWithExpiry(WBMemoryModules.UNREACHABLE_TONGUE_TARGETS.get(), targets, 100L);
}
frog.getBrain().setMemoryWithExpiry(
WBMemoryModules.UNREACHABLE_TONGUE_TARGETS.get(), targets, 100L
);
}
enum Phase {
MOVE_TO_TARGET,
CATCH_ANIMATION,
EAT_ANIMATION,
DONE
}
}
enum Phase { MOVE_TO_TARGET, CATCH_ANIMATION, EAT_ANIMATION, DONE }
}

View file

@ -1,5 +1,12 @@
package com.cursedcauldron.wildbackport.common.entities.brain.frog;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import net.minecraft.core.BlockPos;
@ -26,13 +33,6 @@ import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.Vec3;
import org.jetbrains.annotations.Nullable;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
public class FrogJumpToRandomPos<E extends Mob> extends Behavior<E> {
private static final List<Integer> ANGLES = Lists.newArrayList(65, 70, 75, 80);
private final UniformInt cooldown;
@ -48,8 +48,25 @@ public class FrogJumpToRandomPos<E extends Mob> extends Behavior<E> {
private final Function<E, SoundEvent> landingSound;
private final Predicate<BlockState> landingBlocks;
public FrogJumpToRandomPos(UniformInt cooldown, int yRange, int xzRange, float range, Function<E, SoundEvent> landingSound, Predicate<BlockState> landingBlocks) {
super(ImmutableMap.of(MemoryModuleType.LOOK_TARGET, MemoryStatus.REGISTERED, MemoryModuleType.LONG_JUMP_COOLDOWN_TICKS, MemoryStatus.VALUE_ABSENT, MemoryModuleType.LONG_JUMP_MID_JUMP, MemoryStatus.VALUE_ABSENT), 200);
public FrogJumpToRandomPos(
UniformInt cooldown,
int yRange,
int xzRange,
float range,
Function<E, SoundEvent> landingSound,
Predicate<BlockState> landingBlocks
) {
super(
ImmutableMap.of(
MemoryModuleType.LOOK_TARGET,
MemoryStatus.REGISTERED,
MemoryModuleType.LONG_JUMP_COOLDOWN_TICKS,
MemoryStatus.VALUE_ABSENT,
MemoryModuleType.LONG_JUMP_MID_JUMP,
MemoryStatus.VALUE_ABSENT
),
200
);
this.cooldown = cooldown;
this.yRange = yRange;
this.xzRange = xzRange;
@ -60,16 +77,30 @@ public class FrogJumpToRandomPos<E extends Mob> extends Behavior<E> {
@Override
protected boolean checkExtraStartConditions(ServerLevel level, Mob entity) {
boolean canUse = entity.isOnGround() && !entity.isInWater() && !entity.isInLava() && !level.getBlockState(entity.blockPosition()).is(Blocks.HONEY_BLOCK);
if (!canUse) entity.getBrain().setMemory(MemoryModuleType.LONG_JUMP_COOLDOWN_TICKS, this.cooldown.sample(level.random) / 2);
boolean canUse = entity.isOnGround() && !entity.isInWater() && !entity.isInLava()
&& !level.getBlockState(entity.blockPosition()).is(Blocks.HONEY_BLOCK);
if (!canUse)
entity.getBrain().setMemory(
MemoryModuleType.LONG_JUMP_COOLDOWN_TICKS,
this.cooldown.sample(level.random) / 2
);
return canUse;
}
@Override
protected boolean canStillUse(ServerLevel level, Mob entity, long time) {
boolean canUse = this.lastPos.isPresent() && this.lastPos.get().equals(entity.position()) && this.tries > 0 && !entity.isInWaterOrBubble() && (this.lastTarget != null || !this.targets.isEmpty());
if (!canUse && entity.getBrain().getMemory(MemoryModuleType.LONG_JUMP_MID_JUMP).isEmpty()) {
entity.getBrain().setMemory(MemoryModuleType.LONG_JUMP_COOLDOWN_TICKS, this.cooldown.sample(level.random) / 2);
boolean canUse = this.lastPos.isPresent()
&& this.lastPos.get().equals(entity.position()) && this.tries > 0
&& !entity.isInWaterOrBubble()
&& (this.lastTarget != null || !this.targets.isEmpty());
if (!canUse
&& entity.getBrain()
.getMemory(MemoryModuleType.LONG_JUMP_MID_JUMP)
.isEmpty()) {
entity.getBrain().setMemory(
MemoryModuleType.LONG_JUMP_COOLDOWN_TICKS,
this.cooldown.sample(level.random) / 2
);
entity.getBrain().eraseMemory(MemoryModuleType.LOOK_TARGET);
}
@ -85,7 +116,22 @@ public class FrogJumpToRandomPos<E extends Mob> extends Behavior<E> {
int x = pos.getX();
int y = pos.getY();
int z = pos.getZ();
this.targets = BlockPos.betweenClosedStream(x - this.xzRange, y - this.yRange, z - this.xzRange, x + this.xzRange, y + this.yRange, z + this.xzRange).filter(position -> !position.equals(pos)).map(position -> new Target(position.immutable(), Mth.ceil(pos.distSqr(position)))).collect(Collectors.toCollection(Lists::newArrayList));
this.targets
= BlockPos
.betweenClosedStream(
x - this.xzRange,
y - this.yRange,
z - this.xzRange,
x + this.xzRange,
y + this.yRange,
z + this.xzRange
)
.filter(position -> !position.equals(pos))
.map(
position
-> new Target(position.immutable(), Mth.ceil(pos.distSqr(position)))
)
.collect(Collectors.toCollection(Lists::newArrayList));
}
@Override
@ -98,7 +144,14 @@ public class FrogJumpToRandomPos<E extends Mob> extends Behavior<E> {
double height = length + entity.getJumpBoostPower();
entity.setDeltaMovement(this.lastTarget.scale(height / length));
entity.getBrain().setMemory(MemoryModuleType.LONG_JUMP_MID_JUMP, true);
level.playSound(null, entity, this.landingSound.apply(entity), SoundSource.NEUTRAL, 1.0F, 1.0F);
level.playSound(
null,
entity,
this.landingSound.apply(entity),
SoundSource.NEUTRAL,
1.0F,
1.0F
);
}
} else {
--this.tries;
@ -110,20 +163,26 @@ public class FrogJumpToRandomPos<E extends Mob> extends Behavior<E> {
while (true) {
if (!this.targets.isEmpty()) {
Optional<Target> jumpTarget = this.jumpTarget(level);
if (jumpTarget.isEmpty()) continue;
if (jumpTarget.isEmpty())
continue;
Target target = jumpTarget.get();
BlockPos pos = target.getPos();
if (!canLandOn(level, entity, pos)) continue;
if (!canLandOn(level, entity, pos))
continue;
Vec3 center = Vec3.atCenterOf(pos);
Vec3 lastTarget = this.getRammingVelocity(entity, center);
if (lastTarget == null) continue;
if (lastTarget == null)
continue;
entity.getBrain().setMemory(MemoryModuleType.LOOK_TARGET, new BlockPosTracker(pos));
entity.getBrain().setMemory(
MemoryModuleType.LOOK_TARGET, new BlockPosTracker(pos)
);
PathNavigation navigation = entity.getNavigation();
Path path = navigation.createPath(pos, 0, 8);
if (path != null && path.canReach()) continue;
if (path != null && path.canReach())
continue;
this.lastTarget = lastTarget;
this.targetTime = time;
@ -135,7 +194,8 @@ public class FrogJumpToRandomPos<E extends Mob> extends Behavior<E> {
}
protected Optional<Target> jumpTarget(ServerLevel level) {
Optional<Target> target = WeightedRandom.getRandomItem(level.random, this.targets);
Optional<Target> target
= WeightedRandom.getRandomItem(level.random, this.targets);
target.ifPresent(this.targets::remove);
return target;
}
@ -149,7 +209,10 @@ public class FrogJumpToRandomPos<E extends Mob> extends Behavior<E> {
} else if (!entity.getNavigation().isStableDestination(pos) && !this.landingBlocks.test(level.getBlockState(pos.below()))) {
return false;
} else {
return entity.getPathfindingMalus(WalkNodeEvaluator.getBlockPathTypeStatic(entity.level, pos.mutable())) == 0.0F;
return entity.getPathfindingMalus(WalkNodeEvaluator.getBlockPathTypeStatic(
entity.level, pos.mutable()
))
== 0.0F;
}
}
@ -160,7 +223,8 @@ public class FrogJumpToRandomPos<E extends Mob> extends Behavior<E> {
for (int angle : angles) {
Vec3 velocity = this.getRammingVelocity(entity, pos, angle);
if (velocity != null) return velocity;
if (velocity != null)
return velocity;
}
return null;
@ -169,10 +233,12 @@ public class FrogJumpToRandomPos<E extends Mob> extends Behavior<E> {
@Nullable
private Vec3 getRammingVelocity(Mob entity, Vec3 pos, int angle) {
Vec3 position = entity.position();
Vec3 scale = new Vec3(pos.x - position.x, 0.0, pos.z - position.z).normalize().scale(0.5D);
Vec3 scale = new Vec3(pos.x - position.x, 0.0, pos.z - position.z)
.normalize()
.scale(0.5D);
pos = pos.subtract(scale);
Vec3 distance = pos.subtract(position);
float maxAngle = (float)angle * (float)Math.PI / 180.0F;
float maxAngle = (float) angle * (float) Math.PI / 180.0F;
double xzRange = Math.atan2(distance.z, distance.x);
double yRange = distance.subtract(0.0D, distance.y, 0.0D).lengthSqr();
double yRadius = Math.sqrt(yRange);
@ -187,7 +253,7 @@ public class FrogJumpToRandomPos<E extends Mob> extends Behavior<E> {
return null;
} else {
double range = Math.sqrt(jumpHeight);
if (range > (double)this.maxRange) {
if (range > (double) this.maxRange) {
return null;
} else {
double xzDistance = range * xzMax;
@ -195,21 +261,25 @@ public class FrogJumpToRandomPos<E extends Mob> extends Behavior<E> {
int radius = Mth.ceil(yRadius / xzDistance) * 2;
double index = 0.0;
Vec3 source = null;
for (int j = 0; j < radius - 1; ++j) {
index += yRadius / (double)radius;
index += yRadius / (double) radius;
double x = index * xOffset;
double y = yMax / xzMax * index - Math.pow(index, 2.0) * 0.08 / (2.0 * jumpHeight * Math.pow(xzMax, 2.0));
double y = yMax / xzMax * index
- Math.pow(index, 2.0) * 0.08
/ (2.0 * jumpHeight * Math.pow(xzMax, 2.0));
double z = index * zOffset;
Vec3 target = new Vec3(position.x + x, position.y + y, position.z + z);
Vec3 target
= new Vec3(position.x + x, position.y + y, position.z + z);
if (source != null && !this.canReach(entity, source, target)) {
return null;
}
source = target;
}
return new Vec3(xzDistance * xOffset, yDistance, xzDistance * zOffset).scale(0.95F);
return new Vec3(xzDistance * xOffset, yDistance, xzDistance * zOffset)
.scale(0.95F);
}
}
}
@ -222,7 +292,8 @@ public class FrogJumpToRandomPos<E extends Mob> extends Behavior<E> {
Vec3 normal = distance.normalize();
Vec3 vector = source;
for (int i = 0; i < height; ++i) {
vector = i == height - 1 ? target : vector.add(normal.scale(size * (double)0.9F));
vector = i == height - 1 ? target
: vector.add(normal.scale(size * (double) 0.9F));
AABB box = dimensions.makeBoundingBox(vector);
if (!entity.level.noCollision(entity, box)) {
return false;

View file

@ -1,5 +1,7 @@
package com.cursedcauldron.wildbackport.common.entities.brain.frog;
import java.util.Set;
import com.cursedcauldron.wildbackport.common.registry.entity.WBMemoryModules;
import com.google.common.collect.ImmutableSet;
import net.minecraft.server.level.ServerLevel;
@ -8,10 +10,7 @@ import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.ai.memory.MemoryModuleType;
import net.minecraft.world.entity.ai.sensing.Sensor;
import java.util.Set;
public class IsInWaterSensor extends Sensor<LivingEntity> {
@Override
public Set<MemoryModuleType<?>> requires() {
return ImmutableSet.of(WBMemoryModules.IS_IN_WATER.get());

View file

@ -19,7 +19,14 @@ public class LayFrogSpawn extends Behavior<Frog> {
private final MemoryModuleType<?> triggerMemory;
public LayFrogSpawn(Block block, MemoryModuleType<?> triggerMemory) {
super(ImmutableMap.of(MemoryModuleType.ATTACK_TARGET, MemoryStatus.VALUE_ABSENT, MemoryModuleType.WALK_TARGET, MemoryStatus.VALUE_PRESENT, WBMemoryModules.IS_PREGNANT.get(), MemoryStatus.VALUE_PRESENT));
super(ImmutableMap.of(
MemoryModuleType.ATTACK_TARGET,
MemoryStatus.VALUE_ABSENT,
MemoryModuleType.WALK_TARGET,
MemoryStatus.VALUE_PRESENT,
WBMemoryModules.IS_PREGNANT.get(),
MemoryStatus.VALUE_PRESENT
));
this.frogSpawn = block;
this.triggerMemory = triggerMemory;
}
@ -35,9 +42,17 @@ public class LayFrogSpawn extends Behavior<Frog> {
for (Direction direction : Direction.Plane.HORIZONTAL) {
BlockPos offset = blockPos.relative(direction);
BlockPos above = offset.above();
if (level.getBlockState(offset).is(Blocks.WATER) && level.getBlockState(above).isAir()) {
if (level.getBlockState(offset).is(Blocks.WATER)
&& level.getBlockState(above).isAir()) {
level.setBlock(above, this.frogSpawn.defaultBlockState(), 3);
level.playSound(null, frog, WBSoundEvents.FROG_LAY_SPAWN, SoundSource.BLOCKS, 1.0F, 1.0F);
level.playSound(
null,
frog,
WBSoundEvents.FROG_LAY_SPAWN,
SoundSource.BLOCKS,
1.0F,
1.0F
);
frog.getBrain().eraseMemory(this.triggerMemory);
return;
}

View file

@ -20,7 +20,14 @@ public class WalkTowardsLand extends Behavior<PathfinderMob> {
private long nextStartTime;
public WalkTowardsLand(int distance, float speedModifier) {
super(ImmutableMap.of(MemoryModuleType.ATTACK_TARGET, MemoryStatus.VALUE_ABSENT, MemoryModuleType.WALK_TARGET, MemoryStatus.VALUE_ABSENT, MemoryModuleType.LOOK_TARGET, MemoryStatus.REGISTERED));
super(ImmutableMap.of(
MemoryModuleType.ATTACK_TARGET,
MemoryStatus.VALUE_ABSENT,
MemoryModuleType.WALK_TARGET,
MemoryStatus.VALUE_ABSENT,
MemoryModuleType.LOOK_TARGET,
MemoryStatus.REGISTERED
));
this.distance = distance;
this.speedModifier = speedModifier;
}
@ -42,13 +49,21 @@ public class WalkTowardsLand extends Behavior<PathfinderMob> {
BlockPos.MutableBlockPos mutable = new BlockPos.MutableBlockPos();
CollisionContext context = CollisionContext.of(entity);
for (BlockPos position : BlockPos.withinManhattan(pos, this.distance, this.distance, this.distance)) {
for (BlockPos position : BlockPos.withinManhattan(
pos, this.distance, this.distance, this.distance
)) {
if (position.getX() != pos.getX() || position.getZ() != pos.getZ()) {
BlockState state = level.getBlockState(position);
BlockState landState = level.getBlockState(mutable.setWithOffset(position, Direction.DOWN));
if (!state.is(Blocks.WATER) && level.getFluidState(position).isEmpty() && state.getCollisionShape(level, position, context).isEmpty() && landState.isFaceSturdy(level, mutable, Direction.UP)) {
BlockState landState = level.getBlockState(
mutable.setWithOffset(position, Direction.DOWN)
);
if (!state.is(Blocks.WATER) && level.getFluidState(position).isEmpty()
&& state.getCollisionShape(level, position, context).isEmpty()
&& landState.isFaceSturdy(level, mutable, Direction.UP)) {
this.nextStartTime = time + 60L;
BehaviorUtils.setWalkAndLookTargetMemories(entity, position.immutable(), this.speedModifier, 1);
BehaviorUtils.setWalkAndLookTargetMemories(
entity, position.immutable(), this.speedModifier, 1
);
return;
}
}

View file

@ -21,7 +21,14 @@ public class WalkTowardsWater extends Behavior<AgeableMob> {
private long nextStartTime;
public WalkTowardsWater(int distance, float speedModifier) {
super(ImmutableMap.of(MemoryModuleType.ATTACK_TARGET, MemoryStatus.VALUE_ABSENT, MemoryModuleType.WALK_TARGET, MemoryStatus.VALUE_ABSENT, MemoryModuleType.LOOK_TARGET, MemoryStatus.REGISTERED));
super(ImmutableMap.of(
MemoryModuleType.ATTACK_TARGET,
MemoryStatus.VALUE_ABSENT,
MemoryModuleType.WALK_TARGET,
MemoryStatus.VALUE_ABSENT,
MemoryModuleType.LOOK_TARGET,
MemoryStatus.REGISTERED
));
this.distance = distance;
this.speedModifier = speedModifier;
}
@ -43,13 +50,29 @@ public class WalkTowardsWater extends Behavior<AgeableMob> {
BlockPos pos = entity.blockPosition();
BlockPos.MutableBlockPos mutable = new BlockPos.MutableBlockPos();
for (BlockPos position : BlockPos.withinManhattan(pos, this.distance, this.distance, this.distance)) {
if (position.getX() != pos.getX() || position.getZ() != pos.getZ() && level.getBlockState(position).getCollisionShape(level, position, context).isEmpty() && level.getBlockState(mutable.setWithOffset(position, Direction.DOWN)).getCollisionShape(level, position, context).isEmpty()) {
for (BlockPos position : BlockPos.withinManhattan(
pos, this.distance, this.distance, this.distance
)) {
if (position.getX() != pos.getX()
|| position.getZ() != pos.getZ()
&& level.getBlockState(position)
.getCollisionShape(level, position, context)
.isEmpty()
&& level
.getBlockState(
mutable.setWithOffset(position, Direction.DOWN)
)
.getCollisionShape(level, position, context)
.isEmpty()) {
for (Direction direction : Direction.Plane.HORIZONTAL) {
mutable.setWithOffset(position, direction);
if (level.getBlockState(mutable).isAir() && level.getBlockState(mutable.move(Direction.DOWN)).is(Blocks.WATER)) {
if (level.getBlockState(mutable).isAir()
&& level.getBlockState(mutable.move(Direction.DOWN))
.is(Blocks.WATER)) {
this.nextStartTime = time + 40L;
BehaviorUtils.setWalkAndLookTargetMemories(entity, position, this.speedModifier, 0);
BehaviorUtils.setWalkAndLookTargetMemories(
entity, position, this.speedModifier, 0
);
return;
}
}

View file

@ -1,8 +1,8 @@
package com.cursedcauldron.wildbackport.common.entities.brain.warden;
import com.cursedcauldron.wildbackport.client.registry.WBSoundEvents;
import com.cursedcauldron.wildbackport.common.entities.access.api.Poses;
import com.cursedcauldron.wildbackport.common.entities.Warden;
import com.cursedcauldron.wildbackport.common.entities.access.api.Poses;
import com.google.common.collect.ImmutableMap;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.Entity;
@ -14,7 +14,15 @@ import net.minecraft.world.entity.ai.memory.MemoryStatus;
public class Digging<E extends Warden> extends Behavior<E> {
public Digging(int duration) {
super(ImmutableMap.of(MemoryModuleType.ATTACK_TARGET, MemoryStatus.VALUE_ABSENT, MemoryModuleType.WALK_TARGET, MemoryStatus.VALUE_ABSENT), duration);
super(
ImmutableMap.of(
MemoryModuleType.ATTACK_TARGET,
MemoryStatus.VALUE_ABSENT,
MemoryModuleType.WALK_TARGET,
MemoryStatus.VALUE_ABSENT
),
duration
);
}
@Override

View file

@ -1,8 +1,8 @@
package com.cursedcauldron.wildbackport.common.entities.brain.warden;
import com.cursedcauldron.wildbackport.client.registry.WBSoundEvents;
import com.cursedcauldron.wildbackport.common.entities.access.api.Poses;
import com.cursedcauldron.wildbackport.common.entities.Warden;
import com.cursedcauldron.wildbackport.common.entities.access.api.Poses;
import com.cursedcauldron.wildbackport.common.registry.entity.WBMemoryModules;
import com.google.common.collect.ImmutableMap;
import net.minecraft.server.level.ServerLevel;
@ -15,7 +15,17 @@ import net.minecraft.world.entity.ai.memory.MemoryStatus;
public class Emerging<E extends Warden> extends Behavior<E> {
public Emerging(int duration) {
super(ImmutableMap.of(WBMemoryModules.IS_EMERGING.get(), MemoryStatus.VALUE_PRESENT, MemoryModuleType.WALK_TARGET, MemoryStatus.VALUE_ABSENT, MemoryModuleType.LOOK_TARGET, MemoryStatus.REGISTERED), duration);
super(
ImmutableMap.of(
WBMemoryModules.IS_EMERGING.get(),
MemoryStatus.VALUE_PRESENT,
MemoryModuleType.WALK_TARGET,
MemoryStatus.VALUE_ABSENT,
MemoryModuleType.LOOK_TARGET,
MemoryStatus.REGISTERED
),
duration
);
}
@Override

View file

@ -1,5 +1,8 @@
package com.cursedcauldron.wildbackport.common.entities.brain.warden;
import java.util.Optional;
import java.util.function.Function;
import com.cursedcauldron.wildbackport.common.entities.Warden;
import com.cursedcauldron.wildbackport.common.registry.entity.WBMemoryModules;
import com.google.common.collect.ImmutableMap;
@ -9,14 +12,18 @@ import net.minecraft.world.entity.ai.behavior.Behavior;
import net.minecraft.world.entity.ai.memory.MemoryModuleType;
import net.minecraft.world.entity.ai.memory.MemoryStatus;
import java.util.Optional;
import java.util.function.Function;
public class FindRoarTarget<E extends Warden> extends Behavior<E> {
private final Function<E, Optional<? extends LivingEntity>> targetFinder;
public FindRoarTarget(Function<E, Optional<? extends LivingEntity>> targetFinder) {
super(ImmutableMap.of(WBMemoryModules.ROAR_TARGET.get(), MemoryStatus.VALUE_ABSENT, MemoryModuleType.ATTACK_TARGET, MemoryStatus.VALUE_ABSENT, MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE, MemoryStatus.REGISTERED));
super(ImmutableMap.of(
WBMemoryModules.ROAR_TARGET.get(),
MemoryStatus.VALUE_ABSENT,
MemoryModuleType.ATTACK_TARGET,
MemoryStatus.VALUE_ABSENT,
MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE,
MemoryStatus.REGISTERED
));
this.targetFinder = targetFinder;
}

View file

@ -1,5 +1,9 @@
package com.cursedcauldron.wildbackport.common.entities.brain.warden;
import java.util.Optional;
import java.util.function.BiConsumer;
import java.util.function.Predicate;
import com.google.common.collect.ImmutableMap;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.LivingEntity;
@ -8,17 +12,22 @@ import net.minecraft.world.entity.ai.behavior.Behavior;
import net.minecraft.world.entity.ai.memory.MemoryModuleType;
import net.minecraft.world.entity.ai.memory.MemoryStatus;
import java.util.Optional;
import java.util.function.BiConsumer;
import java.util.function.Predicate;
public class ForgetAttackTarget<E extends Mob> extends Behavior<E> {
private final Predicate<LivingEntity> alternativeCondition;
private final BiConsumer<E, LivingEntity> forgetCallback;
private final boolean shouldForgetIfTargetUnreachable;
public ForgetAttackTarget(Predicate<LivingEntity> alternativeCondition, BiConsumer<E, LivingEntity> forgetCallback, boolean shouldForgetIfTargetUnreachable) {
super(ImmutableMap.of(MemoryModuleType.ATTACK_TARGET, MemoryStatus.VALUE_PRESENT, MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE, MemoryStatus.REGISTERED));
public ForgetAttackTarget(
Predicate<LivingEntity> alternativeCondition,
BiConsumer<E, LivingEntity> forgetCallback,
boolean shouldForgetIfTargetUnreachable
) {
super(ImmutableMap.of(
MemoryModuleType.ATTACK_TARGET,
MemoryStatus.VALUE_PRESENT,
MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE,
MemoryStatus.REGISTERED
));
this.alternativeCondition = alternativeCondition;
this.forgetCallback = forgetCallback;
this.shouldForgetIfTargetUnreachable = shouldForgetIfTargetUnreachable;
@ -49,12 +58,14 @@ public class ForgetAttackTarget<E extends Mob> extends Behavior<E> {
}
private static <E extends LivingEntity> boolean cannotReachTarget(E entity) {
Optional<Long> time = entity.getBrain().getMemory(MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE);
Optional<Long> time
= entity.getBrain().getMemory(MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE);
return time.isPresent() && entity.level.getGameTime() - time.get() > 200L;
}
private boolean isAttackTargetDead(E entity) {
Optional<LivingEntity> target = entity.getBrain().getMemory(MemoryModuleType.ATTACK_TARGET);
Optional<LivingEntity> target
= entity.getBrain().getMemory(MemoryModuleType.ATTACK_TARGET);
return target.isPresent() && !target.get().isAlive();
}

View file

@ -1,5 +1,7 @@
package com.cursedcauldron.wildbackport.common.entities.brain.warden;
import java.util.Random;
import com.google.common.collect.ImmutableMap;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
@ -9,15 +11,26 @@ import net.minecraft.world.entity.ai.behavior.BehaviorUtils;
import net.minecraft.world.entity.ai.memory.MemoryModuleType;
import net.minecraft.world.entity.ai.memory.MemoryStatus;
import java.util.Random;
public class GoToTargetLocation<E extends Mob> extends Behavior<E> {
private final MemoryModuleType<BlockPos> locationMemory;
private final int closeEnoughDistance;
private final float speedModifier;
public GoToTargetLocation(MemoryModuleType<BlockPos> locationMemory, int closeEnoughDistance, float speedModifier) {
super(ImmutableMap.of(locationMemory, MemoryStatus.VALUE_PRESENT, MemoryModuleType.ATTACK_TARGET, MemoryStatus.VALUE_ABSENT, MemoryModuleType.WALK_TARGET, MemoryStatus.VALUE_ABSENT, MemoryModuleType.LOOK_TARGET, MemoryStatus.REGISTERED));
public GoToTargetLocation(
MemoryModuleType<BlockPos> locationMemory,
int closeEnoughDistance,
float speedModifier
) {
super(ImmutableMap.of(
locationMemory,
MemoryStatus.VALUE_PRESENT,
MemoryModuleType.ATTACK_TARGET,
MemoryStatus.VALUE_ABSENT,
MemoryModuleType.WALK_TARGET,
MemoryStatus.VALUE_ABSENT,
MemoryModuleType.LOOK_TARGET,
MemoryStatus.REGISTERED
));
this.locationMemory = locationMemory;
this.closeEnoughDistance = closeEnoughDistance;
this.speedModifier = speedModifier;
@ -26,8 +39,15 @@ public class GoToTargetLocation<E extends Mob> extends Behavior<E> {
@Override
protected void start(ServerLevel level, E entity, long time) {
BlockPos pos = this.getTargetLocation(entity);
boolean inRange = pos.closerThan(entity.blockPosition(), this.closeEnoughDistance);
if (!inRange) BehaviorUtils.setWalkAndLookTargetMemories(entity, getNearbyPos(entity, pos), this.speedModifier, this.closeEnoughDistance);
boolean inRange
= pos.closerThan(entity.blockPosition(), this.closeEnoughDistance);
if (!inRange)
BehaviorUtils.setWalkAndLookTargetMemories(
entity,
getNearbyPos(entity, pos),
this.speedModifier,
this.closeEnoughDistance
);
}
private static BlockPos getNearbyPos(Mob mob, BlockPos pos) {

View file

@ -1,5 +1,9 @@
package com.cursedcauldron.wildbackport.common.entities.brain.warden;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
import com.google.common.collect.ImmutableSet;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.LivingEntity;
@ -8,20 +12,25 @@ import net.minecraft.world.entity.ai.memory.NearestVisibleLivingEntities;
import net.minecraft.world.entity.ai.sensing.Sensor;
import net.minecraft.world.phys.AABB;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
//<>
public class NearestLivingEntitySensor<T extends LivingEntity> extends Sensor<T> {
@Override
protected void doTick(ServerLevel level, T entity) {
AABB box = entity.getBoundingBox().inflate(this.getHorizontalExpansion(), this.getHeightExpansion(), this.getHorizontalExpansion());
List<LivingEntity> entities = level.getEntitiesOfClass(LivingEntity.class, box, target -> target != entity && target.isAlive());
AABB box = entity.getBoundingBox().inflate(
this.getHorizontalExpansion(),
this.getHeightExpansion(),
this.getHorizontalExpansion()
);
List<LivingEntity> entities = level.getEntitiesOfClass(
LivingEntity.class, box, target -> target != entity && target.isAlive()
);
entities.sort(Comparator.comparingDouble(entity::distanceToSqr));
entity.getBrain().setMemory(MemoryModuleType.NEAREST_LIVING_ENTITIES, entities);
entity.getBrain().setMemory(MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES, new NearestVisibleLivingEntities(entity, entities));
entity.getBrain().setMemory(
MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES,
new NearestVisibleLivingEntities(entity, entities)
);
}
protected int getHorizontalExpansion() {
@ -34,6 +43,9 @@ public class NearestLivingEntitySensor<T extends LivingEntity> extends Sensor<T>
@Override
public Set<MemoryModuleType<?>> requires() {
return ImmutableSet.of(MemoryModuleType.NEAREST_LIVING_ENTITIES, MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES);
return ImmutableSet.of(
MemoryModuleType.NEAREST_LIVING_ENTITIES,
MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES
);
}
}

View file

@ -18,15 +18,30 @@ import net.minecraft.world.entity.ai.memory.MemoryStatus;
public class Roar extends Behavior<Warden> {
public Roar() {
super(ImmutableMap.of(WBMemoryModules.ROAR_TARGET.get(), MemoryStatus.VALUE_PRESENT, MemoryModuleType.ATTACK_TARGET, MemoryStatus.VALUE_ABSENT, WBMemoryModules.ROAR_SOUND_COOLDOWN.get(), MemoryStatus.REGISTERED, WBMemoryModules.ROAR_SOUND_DELAY.get(), MemoryStatus.REGISTERED), WardenBrain.ROAR_DURATION);
super(
ImmutableMap.of(
WBMemoryModules.ROAR_TARGET.get(),
MemoryStatus.VALUE_PRESENT,
MemoryModuleType.ATTACK_TARGET,
MemoryStatus.VALUE_ABSENT,
WBMemoryModules.ROAR_SOUND_COOLDOWN.get(),
MemoryStatus.REGISTERED,
WBMemoryModules.ROAR_SOUND_DELAY.get(),
MemoryStatus.REGISTERED
),
WardenBrain.ROAR_DURATION
);
}
@Override
protected void start(ServerLevel level, Warden warden, long time) {
Brain<?> brain = warden.getBrain();
brain.setMemoryWithExpiry(WBMemoryModules.ROAR_SOUND_DELAY.get(), Unit.INSTANCE, 26L);
brain.setMemoryWithExpiry(
WBMemoryModules.ROAR_SOUND_DELAY.get(), Unit.INSTANCE, 26L
);
brain.eraseMemory(MemoryModuleType.WALK_TARGET);
LivingEntity target = warden.getBrain().getMemory(WBMemoryModules.ROAR_TARGET.get()).get();
LivingEntity target
= warden.getBrain().getMemory(WBMemoryModules.ROAR_TARGET.get()).get();
BehaviorUtils.lookAtEntity(warden, target);
warden.setPose(Poses.ROARING.get());
warden.increaseAngerAt(target, 20, false);
@ -39,16 +54,25 @@ public class Roar extends Behavior<Warden> {
@Override
protected void tick(ServerLevel level, Warden warden, long time) {
if (!warden.getBrain().hasMemoryValue(WBMemoryModules.ROAR_SOUND_DELAY.get()) && !warden.getBrain().hasMemoryValue(WBMemoryModules.ROAR_SOUND_COOLDOWN.get())) {
warden.getBrain().setMemoryWithExpiry(WBMemoryModules.ROAR_SOUND_COOLDOWN.get(), Unit.INSTANCE, WardenBrain.ROAR_DURATION - 25);
if (!warden.getBrain().hasMemoryValue(WBMemoryModules.ROAR_SOUND_DELAY.get())
&& !warden.getBrain().hasMemoryValue(WBMemoryModules.ROAR_SOUND_COOLDOWN.get()
)) {
warden.getBrain().setMemoryWithExpiry(
WBMemoryModules.ROAR_SOUND_COOLDOWN.get(),
Unit.INSTANCE,
WardenBrain.ROAR_DURATION - 25
);
warden.playSound(WBSoundEvents.WARDEN_ROAR, 3.0F, 1.0F);
}
}
@Override
protected void stop(ServerLevel level, Warden warden, long time) {
if (warden.hasPose(Poses.ROARING.get())) warden.setPose(Pose.STANDING);
warden.getBrain().getMemory(WBMemoryModules.ROAR_TARGET.get()).ifPresent(warden::updateAttackTarget);
if (warden.hasPose(Poses.ROARING.get()))
warden.setPose(Pose.STANDING);
warden.getBrain()
.getMemory(WBMemoryModules.ROAR_TARGET.get())
.ifPresent(warden::updateAttackTarget);
warden.getBrain().eraseMemory(WBMemoryModules.ROAR_TARGET.get());
}
}

View file

@ -15,17 +15,35 @@ import net.minecraft.world.entity.ai.memory.MemoryStatus;
public class SetWardenLookTarget extends Behavior<Warden> {
public SetWardenLookTarget() {
super(ImmutableMap.of(WBMemoryModules.DISTURBANCE_LOCATION.get(), MemoryStatus.REGISTERED, WBMemoryModules.ROAR_TARGET.get(), MemoryStatus.REGISTERED, MemoryModuleType.ATTACK_TARGET, MemoryStatus.VALUE_ABSENT));
super(ImmutableMap.of(
WBMemoryModules.DISTURBANCE_LOCATION.get(),
MemoryStatus.REGISTERED,
WBMemoryModules.ROAR_TARGET.get(),
MemoryStatus.REGISTERED,
MemoryModuleType.ATTACK_TARGET,
MemoryStatus.VALUE_ABSENT
));
}
@Override
protected boolean checkExtraStartConditions(ServerLevel level, Warden warden) {
return warden.getBrain().hasMemoryValue(WBMemoryModules.DISTURBANCE_LOCATION.get()) || warden.getBrain().hasMemoryValue(WBMemoryModules.ROAR_TARGET.get());
return warden.getBrain().hasMemoryValue(WBMemoryModules.DISTURBANCE_LOCATION.get()
)
|| warden.getBrain().hasMemoryValue(WBMemoryModules.ROAR_TARGET.get());
}
@Override
protected void start(ServerLevel level, Warden warden, long time) {
BlockPos pos = warden.getBrain().getMemory(WBMemoryModules.ROAR_TARGET.get()).map(Entity::blockPosition).or(() -> warden.getBrain().getMemory(WBMemoryModules.DISTURBANCE_LOCATION.get())).get();
warden.getBrain().setMemory(MemoryModuleType.LOOK_TARGET, new BlockPosTracker(pos));
BlockPos pos = warden.getBrain()
.getMemory(WBMemoryModules.ROAR_TARGET.get())
.map(Entity::blockPosition)
.or(()
-> warden.getBrain().getMemory(
WBMemoryModules.DISTURBANCE_LOCATION.get()
))
.get();
warden.getBrain().setMemory(
MemoryModuleType.LOOK_TARGET, new BlockPosTracker(pos)
);
}
}

View file

@ -1,8 +1,8 @@
package com.cursedcauldron.wildbackport.common.entities.brain.warden;
import com.cursedcauldron.wildbackport.client.registry.WBSoundEvents;
import com.cursedcauldron.wildbackport.common.entities.access.api.Poses;
import com.cursedcauldron.wildbackport.common.entities.Warden;
import com.cursedcauldron.wildbackport.common.entities.access.api.Poses;
import com.cursedcauldron.wildbackport.common.entities.brain.WardenBrain;
import com.cursedcauldron.wildbackport.common.registry.entity.WBMemoryModules;
import com.google.common.collect.ImmutableMap;
@ -14,7 +14,25 @@ import net.minecraft.world.entity.ai.memory.MemoryStatus;
public class Sniffing<E extends Warden> extends Behavior<E> {
public Sniffing(int duration) {
super(ImmutableMap.of(WBMemoryModules.IS_SNIFFING.get(), MemoryStatus.VALUE_PRESENT, MemoryModuleType.ATTACK_TARGET, MemoryStatus.VALUE_ABSENT, MemoryModuleType.WALK_TARGET, MemoryStatus.VALUE_ABSENT, MemoryModuleType.LOOK_TARGET, MemoryStatus.REGISTERED, MemoryModuleType.NEAREST_ATTACKABLE, MemoryStatus.REGISTERED, WBMemoryModules.DISTURBANCE_LOCATION.get(), MemoryStatus.REGISTERED, WBMemoryModules.SNIFF_COOLDOWN.get(), MemoryStatus.REGISTERED), duration);
super(
ImmutableMap.of(
WBMemoryModules.IS_SNIFFING.get(),
MemoryStatus.VALUE_PRESENT,
MemoryModuleType.ATTACK_TARGET,
MemoryStatus.VALUE_ABSENT,
MemoryModuleType.WALK_TARGET,
MemoryStatus.VALUE_ABSENT,
MemoryModuleType.LOOK_TARGET,
MemoryStatus.REGISTERED,
MemoryModuleType.NEAREST_ATTACKABLE,
MemoryStatus.REGISTERED,
WBMemoryModules.DISTURBANCE_LOCATION.get(),
MemoryStatus.REGISTERED,
WBMemoryModules.SNIFF_COOLDOWN.get(),
MemoryStatus.REGISTERED
),
duration
);
}
@Override
@ -34,14 +52,19 @@ public class Sniffing<E extends Warden> extends Behavior<E> {
}
entity.getBrain().eraseMemory(WBMemoryModules.IS_SNIFFING.get());
entity.getBrain().getMemory(MemoryModuleType.NEAREST_ATTACKABLE).filter(entity::isValidTarget).ifPresent(target -> {
if (entity.closerThan(target, 6.0D, 20.0D)) {
entity.increaseAngerAt(target);
}
entity.getBrain()
.getMemory(MemoryModuleType.NEAREST_ATTACKABLE)
.filter(entity::isValidTarget)
.ifPresent(target -> {
if (entity.closerThan(target, 6.0D, 20.0D)) {
entity.increaseAngerAt(target);
}
if (!entity.getBrain().hasMemoryValue(WBMemoryModules.DISTURBANCE_LOCATION.get())) {
WardenBrain.lookAtDisturbance(entity, target.blockPosition());
}
});
if (!entity.getBrain().hasMemoryValue(
WBMemoryModules.DISTURBANCE_LOCATION.get()
)) {
WardenBrain.lookAtDisturbance(entity, target.blockPosition());
}
});
}
}

View file

@ -26,12 +26,28 @@ public class SonicBoom extends Behavior<Warden> {
private static final int DURATION = Mth.ceil(60.0F);
public SonicBoom() {
super(ImmutableMap.of(MemoryModuleType.ATTACK_TARGET, MemoryStatus.VALUE_PRESENT, WBMemoryModules.SONIC_BOOM_COOLDOWN.get(), MemoryStatus.VALUE_ABSENT, WBMemoryModules.SONIC_BOOM_SOUND_COOLDOWN.get(), MemoryStatus.REGISTERED, WBMemoryModules.SONIC_BOOM_SOUND_DELAY.get(), MemoryStatus.REGISTERED), DURATION);
super(
ImmutableMap.of(
MemoryModuleType.ATTACK_TARGET,
MemoryStatus.VALUE_PRESENT,
WBMemoryModules.SONIC_BOOM_COOLDOWN.get(),
MemoryStatus.VALUE_ABSENT,
WBMemoryModules.SONIC_BOOM_SOUND_COOLDOWN.get(),
MemoryStatus.REGISTERED,
WBMemoryModules.SONIC_BOOM_SOUND_DELAY.get(),
MemoryStatus.REGISTERED
),
DURATION
);
}
@Override
protected boolean checkExtraStartConditions(ServerLevel level, Warden warden) {
return warden.closerThan(warden.getBrain().getMemory(MemoryModuleType.ATTACK_TARGET).get(), 15.0D, 20.0D);
return warden.closerThan(
warden.getBrain().getMemory(MemoryModuleType.ATTACK_TARGET).get(),
15.0D,
20.0D
);
}
@Override
@ -41,33 +57,69 @@ public class SonicBoom extends Behavior<Warden> {
@Override
protected void start(ServerLevel level, Warden warden, long time) {
warden.getBrain().setMemoryWithExpiry(MemoryModuleType.ATTACK_COOLING_DOWN, true, DURATION);
warden.getBrain().setMemoryWithExpiry(WBMemoryModules.SONIC_BOOM_SOUND_DELAY.get(), Unit.INSTANCE, SOUND_DELAY + 5);
warden.getBrain().setMemoryWithExpiry(
MemoryModuleType.ATTACK_COOLING_DOWN, true, DURATION
);
warden.getBrain().setMemoryWithExpiry(
WBMemoryModules.SONIC_BOOM_SOUND_DELAY.get(), Unit.INSTANCE, SOUND_DELAY + 5
);
level.broadcastEntityEvent(warden, Warden.SONIC_BOOM);
warden.playSound(WBSoundEvents.WARDEN_SONIC_CHARGE, 3.0F, 1.0F);
}
@Override
protected void tick(ServerLevel level, Warden warden, long time) {
warden.getBrain().getMemory(MemoryModuleType.ATTACK_TARGET).ifPresent(target -> warden.getLookControl().setLookAt(target.position()));
if (!warden.getBrain().hasMemoryValue(WBMemoryModules.SONIC_BOOM_SOUND_DELAY.get()) && !warden.getBrain().hasMemoryValue(WBMemoryModules.SONIC_BOOM_SOUND_COOLDOWN.get())) {
warden.getBrain().setMemoryWithExpiry(WBMemoryModules.SONIC_BOOM_SOUND_COOLDOWN.get(), Unit.INSTANCE, DURATION - SOUND_DELAY + 5);
warden.getBrain().getMemory(MemoryModuleType.ATTACK_TARGET).filter(warden::isValidTarget).filter(target -> warden.closerThan(target, 15.0D, 20.0D)).ifPresent(target -> {
Vec3 sourcePos = warden.position().add(0.0D, 1.6F, 0.0D);
Vec3 targetPos = target.getEyePosition().subtract(sourcePos);
Vec3 distance = targetPos.normalize();
warden.getBrain()
.getMemory(MemoryModuleType.ATTACK_TARGET)
.ifPresent(target -> warden.getLookControl().setLookAt(target.position()));
if (!warden.getBrain().hasMemoryValue(WBMemoryModules.SONIC_BOOM_SOUND_DELAY.get()
)
&& !warden.getBrain().hasMemoryValue(
WBMemoryModules.SONIC_BOOM_SOUND_COOLDOWN.get()
)) {
warden.getBrain().setMemoryWithExpiry(
WBMemoryModules.SONIC_BOOM_SOUND_COOLDOWN.get(),
Unit.INSTANCE,
DURATION - SOUND_DELAY + 5
);
warden.getBrain()
.getMemory(MemoryModuleType.ATTACK_TARGET)
.filter(warden::isValidTarget)
.filter(target -> warden.closerThan(target, 15.0D, 20.0D))
.ifPresent(target -> {
Vec3 sourcePos = warden.position().add(0.0D, 1.6F, 0.0D);
Vec3 targetPos = target.getEyePosition().subtract(sourcePos);
Vec3 distance = targetPos.normalize();
for(int i = 1; i < Mth.floor(targetPos.length()) + 7; ++i) {
Vec3 charge = sourcePos.add(distance.scale(i));
level.sendParticles(WBParticleTypes.SONIC_BOOM.get(), charge.x, charge.y, charge.z, 1, 0.0D, 0.0D, 0.0D, 0.0D);
}
for (int i = 1; i < Mth.floor(targetPos.length()) + 7; ++i) {
Vec3 charge = sourcePos.add(distance.scale(i));
level.sendParticles(
WBParticleTypes.SONIC_BOOM.get(),
charge.x,
charge.y,
charge.z,
1,
0.0D,
0.0D,
0.0D,
0.0D
);
}
warden.playSound(WBSoundEvents.WARDEN_SONIC_BOOM, 3.0F, 1.0F);
target.hurt(sonicBoom(warden), 10.0F);
double yKnockback = 0.5D * (1.0D - target.getAttributeValue(Attributes.KNOCKBACK_RESISTANCE));
double xzKnockback = 2.5D * (1.0D - target.getAttributeValue(Attributes.KNOCKBACK_RESISTANCE));
target.push(distance.x() * xzKnockback, distance.y() * yKnockback, distance.z() * xzKnockback);
});
warden.playSound(WBSoundEvents.WARDEN_SONIC_BOOM, 3.0F, 1.0F);
target.hurt(sonicBoom(warden), 10.0F);
double yKnockback = 0.5D
* (1.0D
- target.getAttributeValue(Attributes.KNOCKBACK_RESISTANCE));
double xzKnockback = 2.5D
* (1.0D
- target.getAttributeValue(Attributes.KNOCKBACK_RESISTANCE));
target.push(
distance.x() * xzKnockback,
distance.y() * yKnockback,
distance.z() * xzKnockback
);
});
}
}
@ -77,11 +129,15 @@ public class SonicBoom extends Behavior<Warden> {
}
public static void setCooldown(LivingEntity entity, long cooldown) {
entity.getBrain().setMemoryWithExpiry(WBMemoryModules.SONIC_BOOM_COOLDOWN.get(), Unit.INSTANCE, cooldown);
entity.getBrain().setMemoryWithExpiry(
WBMemoryModules.SONIC_BOOM_COOLDOWN.get(), Unit.INSTANCE, cooldown
);
}
@SuppressWarnings("ConstantConditions")
public static DamageSource sonicBoom(Entity entity) {
return ((DamageSourceAccessor)new EntityDamageSource("sonic_boom", entity)).callBypassArmor().setMagic();
return ((DamageSourceAccessor) new EntityDamageSource("sonic_boom", entity))
.callBypassArmor()
.setMagic();
}
}

View file

@ -1,7 +1,7 @@
package com.cursedcauldron.wildbackport.common.entities.brain.warden;
import com.cursedcauldron.wildbackport.common.entities.access.api.Poses;
import com.cursedcauldron.wildbackport.common.entities.Warden;
import com.cursedcauldron.wildbackport.common.entities.access.api.Poses;
import com.cursedcauldron.wildbackport.common.registry.entity.WBMemoryModules;
import com.google.common.collect.ImmutableMap;
import net.minecraft.server.level.ServerLevel;
@ -16,13 +16,24 @@ public class TryToSniff extends Behavior<Warden> {
private static final IntProvider SNIFF_COOLDOWN = UniformInt.of(100, 200);
public TryToSniff() {
super(ImmutableMap.of(WBMemoryModules.SNIFF_COOLDOWN.get(), MemoryStatus.VALUE_ABSENT, MemoryModuleType.NEAREST_ATTACKABLE, MemoryStatus.VALUE_PRESENT, WBMemoryModules.DISTURBANCE_LOCATION.get(), MemoryStatus.VALUE_ABSENT));
super(ImmutableMap.of(
WBMemoryModules.SNIFF_COOLDOWN.get(),
MemoryStatus.VALUE_ABSENT,
MemoryModuleType.NEAREST_ATTACKABLE,
MemoryStatus.VALUE_PRESENT,
WBMemoryModules.DISTURBANCE_LOCATION.get(),
MemoryStatus.VALUE_ABSENT
));
}
@Override
protected void start(ServerLevel level, Warden warden, long time) {
warden.getBrain().setMemory(WBMemoryModules.IS_SNIFFING.get(), Unit.INSTANCE);
warden.getBrain().setMemoryWithExpiry(WBMemoryModules.SNIFF_COOLDOWN.get(), Unit.INSTANCE, SNIFF_COOLDOWN.sample(level.getRandom()));
warden.getBrain().setMemoryWithExpiry(
WBMemoryModules.SNIFF_COOLDOWN.get(),
Unit.INSTANCE,
SNIFF_COOLDOWN.sample(level.getRandom())
);
warden.getBrain().eraseMemory(MemoryModuleType.WALK_TARGET);
warden.setPose(Poses.SNIFFING.get());
}

View file

@ -1,5 +1,11 @@
package com.cursedcauldron.wildbackport.common.entities.brain.warden;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.function.Predicate;
import com.cursedcauldron.wildbackport.common.entities.Warden;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
@ -8,26 +14,40 @@ import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.ai.memory.MemoryModuleType;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.function.Predicate;
public class WardenEntitySensor extends NearestLivingEntitySensor<Warden> {
@Override
public Set<MemoryModuleType<?>> requires() {
return ImmutableSet.copyOf(Iterables.concat(super.requires(), List.of(MemoryModuleType.NEAREST_ATTACKABLE)));
return ImmutableSet.copyOf(Iterables.concat(
super.requires(), List.of(MemoryModuleType.NEAREST_ATTACKABLE)
));
}
@Override
protected void doTick(ServerLevel level, Warden warden) {
super.doTick(level, warden);
findNearestTarget(warden, target -> target.getType() == EntityType.PLAYER).or(() -> findNearestTarget(warden, target -> target.getType() != EntityType.PLAYER)).ifPresentOrElse(target -> warden.getBrain().setMemory(MemoryModuleType.NEAREST_ATTACKABLE, target), () -> warden.getBrain().eraseMemory(MemoryModuleType.NEAREST_ATTACKABLE));
findNearestTarget(warden, target -> target.getType() == EntityType.PLAYER)
.or(()
-> findNearestTarget(
warden, target -> target.getType() != EntityType.PLAYER
))
.ifPresentOrElse(
target
-> warden.getBrain().setMemory(
MemoryModuleType.NEAREST_ATTACKABLE, target
),
() -> warden.getBrain().eraseMemory(MemoryModuleType.NEAREST_ATTACKABLE)
);
}
private static Optional<LivingEntity> findNearestTarget(Warden warden, Predicate<LivingEntity> targetPredicate) {
return warden.getBrain().getMemory(MemoryModuleType.NEAREST_LIVING_ENTITIES).stream().flatMap(Collection::stream).filter(warden::isValidTarget).filter(targetPredicate).findFirst();
private static Optional<LivingEntity>
findNearestTarget(Warden warden, Predicate<LivingEntity> targetPredicate) {
return warden.getBrain()
.getMemory(MemoryModuleType.NEAREST_LIVING_ENTITIES)
.stream()
.flatMap(Collection::stream)
.filter(warden::isValidTarget)
.filter(targetPredicate)
.findFirst();
}
@Override

View file

@ -1,11 +1,11 @@
package com.cursedcauldron.wildbackport.common.entities.warden;
import java.util.Arrays;
import com.cursedcauldron.wildbackport.client.registry.WBSoundEvents;
import net.minecraft.Util;
import net.minecraft.sounds.SoundEvent;
import java.util.Arrays;
//<>
public enum Angriness {
@ -13,7 +13,10 @@ public enum Angriness {
AGITATED(40, WBSoundEvents.WARDEN_AGITATED, WBSoundEvents.WARDEN_LISTENING_ANGRY),
ANGRY(80, WBSoundEvents.WARDEN_ANGRY, WBSoundEvents.WARDEN_LISTENING_ANGRY);
private static final Angriness[] VALUES = Util.make(Angriness.values(), values -> Arrays.sort(values, (a, b) -> Integer.compare(b.threshold, a.threshold)));
private static final Angriness[] VALUES = Util.make(
Angriness.values(),
values -> Arrays.sort(values, (a, b) -> Integer.compare(b.threshold, a.threshold))
);
private final int threshold;
private final SoundEvent sound;
private final SoundEvent listeningSound;

View file

@ -1,5 +1,9 @@
package com.cursedcauldron.wildbackport.common.entities.warden;
import java.util.Optional;
import java.util.UUID;
import java.util.function.Function;
import com.cursedcauldron.wildbackport.common.registry.WBPositionSources;
import com.mojang.datafixers.util.Either;
import com.mojang.serialization.Codec;
@ -13,12 +17,25 @@ import net.minecraft.world.level.Level;
import net.minecraft.world.level.gameevent.PositionSource;
import net.minecraft.world.level.gameevent.PositionSourceType;
import java.util.Optional;
import java.util.UUID;
import java.util.function.Function;
public class MobPositionSource implements PositionSource {
public static final Codec<MobPositionSource> CODEC = RecordCodecBuilder.create(instance -> instance.group((SerializableUUID.CODEC.fieldOf("source_entity")).forGetter(MobPositionSource::getUuid), (Codec.FLOAT.fieldOf("y_offset")).orElse(0.0f).forGetter(entityPositionSource -> entityPositionSource.yOffset)).apply(instance, (uUID, float_) -> new MobPositionSource(Either.right(Either.left(uUID)), float_.floatValue())));
public static final Codec<MobPositionSource> CODEC = RecordCodecBuilder.create(
instance
-> instance
.group(
(SerializableUUID.CODEC.fieldOf("source_entity"))
.forGetter(MobPositionSource::getUuid),
(Codec.FLOAT.fieldOf("y_offset"))
.orElse(0.0f)
.forGetter(entityPositionSource -> entityPositionSource.yOffset)
)
.apply(
instance,
(uUID, float_)
-> new MobPositionSource(
Either.right(Either.left(uUID)), float_.floatValue()
)
)
);
private Either<Entity, Either<UUID, Integer>> source;
final float yOffset;
@ -26,7 +43,9 @@ public class MobPositionSource implements PositionSource {
this(Either.left(entity), yOffset);
}
public MobPositionSource(Either<Entity, Either<UUID, Integer>> sourceEntityId, float yOffset) {
public MobPositionSource(
Either<Entity, Either<UUID, Integer>> sourceEntityId, float yOffset
) {
this.source = sourceEntityId;
this.yOffset = yOffset;
}
@ -36,21 +55,31 @@ public class MobPositionSource implements PositionSource {
if (this.source.left().isEmpty()) {
this.findEntityInWorld(world);
}
return this.source.left().map(entity -> entity.blockPosition().offset(0.0, this.yOffset, 0.0));
return this.source.left().map(
entity -> entity.blockPosition().offset(0.0, this.yOffset, 0.0)
);
}
private void findEntityInWorld(Level world) {
this.source.map(Optional::of, either -> Optional.ofNullable(either.map(uuid -> {
Entity entity;
if (world instanceof ServerLevel serverLevel) {
entity = serverLevel.getEntity(uuid);
} else {
entity = null;
}
return entity;
}, world::getEntity))).ifPresent(entity -> {
this.source = Either.left(entity);
});
this.source
.map(
Optional::of,
either
-> Optional.ofNullable(either.map(
uuid
-> {
Entity entity;
if (world instanceof ServerLevel serverLevel) {
entity = serverLevel.getEntity(uuid);
} else {
entity = null;
}
return entity;
},
world::getEntity
))
)
.ifPresent(entity -> { this.source = Either.left(entity); });
}
@Override
@ -59,9 +88,10 @@ public class MobPositionSource implements PositionSource {
}
private UUID getUuid() {
return this.source.map(Entity::getUUID, either -> either.map(Function.identity(), integer -> {
throw new RuntimeException("Unable to get entityId from uuid");
}));
return this.source
.map(Entity::getUUID, either -> either.map(Function.identity(), integer -> {
throw new RuntimeException("Unable to get entityId from uuid");
}));
}
int getEntityId() {
@ -73,7 +103,9 @@ public class MobPositionSource implements PositionSource {
public static class Type implements PositionSourceType<MobPositionSource> {
@Override
public MobPositionSource read(FriendlyByteBuf buf) {
return new MobPositionSource(Either.right(Either.right(buf.readVarInt())), buf.readFloat());
return new MobPositionSource(
Either.right(Either.right(buf.readVarInt())), buf.readFloat()
);
}
@Override

View file

@ -1,5 +1,8 @@
package com.cursedcauldron.wildbackport.common.entities.warden;
import java.util.Optional;
import java.util.UUID;
import com.cursedcauldron.wildbackport.client.registry.WBCriteriaTriggers;
import com.cursedcauldron.wildbackport.common.utils.PositionUtils;
import com.mojang.serialization.Codec;
@ -27,38 +30,54 @@ import net.minecraft.world.phys.HitResult;
import net.minecraft.world.phys.Vec3;
import org.jetbrains.annotations.Nullable;
import java.util.Optional;
import java.util.UUID;
//<>
public class VibrationHandler implements GameEventListener {
protected final PositionSource source;
protected final int range;
protected final VibrationConfig config;
@Nullable protected Vibration event;
@Nullable
protected Vibration event;
protected float distance;
protected int delay;
public static Codec<VibrationHandler> codec(VibrationConfig config) {
return RecordCodecBuilder.create(instance -> {
return instance.group(PositionSource.CODEC.fieldOf("source").forGetter(listener -> {
return listener.source;
}), ExtraCodecs.NON_NEGATIVE_INT.fieldOf("range").forGetter(listener -> {
return listener.range;
}), Vibration.CODEC.optionalFieldOf("event").forGetter(listener -> {
return Optional.ofNullable(listener.event);
}), Codec.floatRange(0.0F, Float.MAX_VALUE).fieldOf("event_distance").orElse(0.0F).forGetter(listener -> {
return listener.distance;
}), ExtraCodecs.NON_NEGATIVE_INT.fieldOf("event_delay").orElse(0).forGetter(listener -> {
return listener.delay;
})).apply(instance, (source, range, event, distance, delay) -> {
return new VibrationHandler(source, range, config, event.orElse(null), distance, delay);
});
return instance
.group(
PositionSource.CODEC.fieldOf("source").forGetter(listener -> {
return listener.source;
}),
ExtraCodecs.NON_NEGATIVE_INT.fieldOf("range").forGetter(listener -> {
return listener.range;
}),
Vibration.CODEC.optionalFieldOf("event").forGetter(listener -> {
return Optional.ofNullable(listener.event);
}),
Codec.floatRange(0.0F, Float.MAX_VALUE)
.fieldOf("event_distance")
.orElse(0.0F)
.forGetter(listener -> { return listener.distance; }),
ExtraCodecs.NON_NEGATIVE_INT.fieldOf("event_delay")
.orElse(0)
.forGetter(listener -> { return listener.delay; })
)
.apply(instance, (source, range, event, distance, delay) -> {
return new VibrationHandler(
source, range, config, event.orElse(null), distance, delay
);
});
});
}
public VibrationHandler(PositionSource source, int range, VibrationConfig config, @Nullable Vibration event, float distance, int delay) {
public VibrationHandler(
PositionSource source,
int range,
VibrationConfig config,
@Nullable Vibration event,
float distance,
int delay
) {
this.source = source;
this.range = range;
this.config = config;
@ -77,7 +96,15 @@ public class VibrationHandler implements GameEventListener {
--this.delay;
if (this.delay <= 0) {
this.delay = 0;
this.config.onSignalReceive(server, this, new BlockPos(this.event.pos), this.event.event, this.event.getEntity(server).orElse(null), this.event.getProjectileOwner(server).orElse(null), this.distance);
this.config.onSignalReceive(
server,
this,
new BlockPos(this.event.pos),
this.event.event,
this.event.getEntity(server).orElse(null),
this.event.getProjectileOwner(server).orElse(null),
this.distance
);
this.event = null;
}
}
@ -95,9 +122,10 @@ public class VibrationHandler implements GameEventListener {
}
@Override
public boolean handleGameEvent(Level level, GameEvent event, @Nullable Entity entity, BlockPos pos) {
public boolean
handleGameEvent(Level level, GameEvent event, @Nullable Entity entity, BlockPos pos) {
if (this.event != null) {
return false;
return false;
} else {
Optional<BlockPos> optional = this.source.getPosition(level);
if (!this.config.isValidVibration(event, entity)) {
@ -105,7 +133,9 @@ public class VibrationHandler implements GameEventListener {
} else {
Vec3 source = PositionUtils.toVec(pos);
Vec3 target = PositionUtils.toVec(optional.get());
if (!this.config.shouldListen((ServerLevel)level, this, new BlockPos(source), event, entity)) {
if (!this.config.shouldListen(
(ServerLevel) level, this, new BlockPos(source), event, entity
)) {
return false;
} else if (isOccluded(level, source, target)) {
return false;
@ -117,23 +147,43 @@ public class VibrationHandler implements GameEventListener {
}
}
private void scheduleSignal(Level level, GameEvent event, @Nullable Entity entity, Vec3 source, Vec3 target) {
this.distance = (float)source.distanceTo(target);
private void scheduleSignal(
Level level, GameEvent event, @Nullable Entity entity, Vec3 source, Vec3 target
) {
this.distance = (float) source.distanceTo(target);
this.event = new Vibration(event, this.distance, source, entity);
this.delay = Mth.floor(this.distance);
((ServerLevel)level).sendVibrationParticle(new VibrationPath(PositionUtils.toBlockPos(source), this.source, this.delay));
((ServerLevel) level)
.sendVibrationParticle(new VibrationPath(
PositionUtils.toBlockPos(source), this.source, this.delay
));
this.config.onSignalSchedule();
}
private static boolean isOccluded(Level level, Vec3 source, Vec3 target) {
Vec3 sourceVec = new Vec3((double)Mth.floor(source.x) + 0.5D, (double)Mth.floor(source.y) + 0.5D, (double)Mth.floor(source.z) + 0.5D);
Vec3 targetVec = new Vec3((double)Mth.floor(target.x) + 0.5D, (double)Mth.floor(target.y) + 0.5D, (double)Mth.floor(target.z) + 0.5D);
Vec3 sourceVec = new Vec3(
(double) Mth.floor(source.x) + 0.5D,
(double) Mth.floor(source.y) + 0.5D,
(double) Mth.floor(source.z) + 0.5D
);
Vec3 targetVec = new Vec3(
(double) Mth.floor(target.x) + 0.5D,
(double) Mth.floor(target.y) + 0.5D,
(double) Mth.floor(target.z) + 0.5D
);
for (Direction direction : Direction.values()) {
Vec3 offsetVec = PositionUtils.relative(sourceVec, direction, 1.0E-5F);
if (level.isBlockInLine(new ClipBlockStateContext(offsetVec, targetVec, state -> {
return state.is(BlockTags.OCCLUDES_VIBRATION_SIGNALS);
})).getType() != HitResult.Type.BLOCK) {
if (level
.isBlockInLine(new ClipBlockStateContext(
offsetVec,
targetVec,
state -> {
return state.is(BlockTags.OCCLUDES_VIBRATION_SIGNALS);
}
))
.getType()
!= HitResult.Type.BLOCK) {
return false;
}
}
@ -141,23 +191,66 @@ public class VibrationHandler implements GameEventListener {
return true;
}
public record Vibration(GameEvent event, float distance, Vec3 pos, @Nullable UUID source, @Nullable UUID projectileOwner, @Nullable Entity entity) {
public static final Codec<Vibration> CODEC = RecordCodecBuilder.create(instance -> {
return instance.group(Registry.GAME_EVENT.byNameCodec().fieldOf("game_event").forGetter(Vibration::event), Codec.floatRange(0.0F, Float.MAX_VALUE).fieldOf("distance").forGetter(Vibration::distance), PositionUtils.VEC_CODEC.fieldOf("pos").forGetter(Vibration::pos), SerializableUUID.CODEC.optionalFieldOf("source").forGetter(entity -> {
return Optional.ofNullable(entity.source());
}), SerializableUUID.CODEC.optionalFieldOf("projectile_owner").forGetter(entity -> {
return Optional.ofNullable(entity.projectileOwner());
})).apply(instance, (event, distance, pos, source, projectileOwner) -> {
return new Vibration(event, distance, pos, source.orElse(null), projectileOwner.orElse(null));
});
});
public record Vibration(
GameEvent event,
float distance,
Vec3 pos,
@Nullable UUID source,
@Nullable UUID projectileOwner,
@Nullable Entity entity
) {
public static final Codec<Vibration> CODEC = RecordCodecBuilder.create(
instance -> {
return instance
.group(
Registry.GAME_EVENT.byNameCodec()
.fieldOf("game_event")
.forGetter(Vibration::event),
Codec.floatRange(0.0F, Float.MAX_VALUE)
.fieldOf("distance")
.forGetter(Vibration::distance),
PositionUtils.VEC_CODEC.fieldOf("pos").forGetter(Vibration::pos),
SerializableUUID.CODEC.optionalFieldOf("source").forGetter(
entity -> { return Optional.ofNullable(entity.source()); }
),
SerializableUUID.CODEC.optionalFieldOf("projectile_owner")
.forGetter(entity -> {
return Optional.ofNullable(entity.projectileOwner());
})
)
.apply(instance, (event, distance, pos, source, projectileOwner) -> {
return new Vibration(
event,
distance,
pos,
source.orElse(null),
projectileOwner.orElse(null)
);
});
}
);
public Vibration(GameEvent event, float distance, Vec3 pos, @Nullable UUID source, @Nullable UUID projectileOwner) {
public Vibration(
GameEvent event,
float distance,
Vec3 pos,
@Nullable UUID source,
@Nullable UUID projectileOwner
) {
this(event, distance, pos, source, projectileOwner, null);
}
public Vibration(GameEvent event, float distance, Vec3 pos, @Nullable Entity entity) {
this(event, distance, pos, entity == null ? null : entity.getUUID(), getProjectileOwner(entity), entity);
public Vibration(
GameEvent event, float distance, Vec3 pos, @Nullable Entity entity
) {
this(
event,
distance,
pos,
entity == null ? null : entity.getUUID(),
getProjectileOwner(entity),
entity
);
}
@Nullable
@ -178,13 +271,14 @@ public class VibrationHandler implements GameEventListener {
}
public Optional<Entity> getProjectileOwner(ServerLevel level) {
return this.getEntity(level).filter(entity -> {
return entity instanceof Projectile;
}).map(entity -> {
return (Projectile)entity;
}).map(Projectile::getOwner).or(() -> {
return Optional.ofNullable(this.projectileOwner).map(level::getEntity);
});
return this.getEntity(level)
.filter(entity -> { return entity instanceof Projectile; })
.map(entity -> { return (Projectile) entity; })
.map(Projectile::getOwner)
.or(() -> {
return Optional.ofNullable(this.projectileOwner)
.map(level::getEntity);
});
}
}
@ -198,7 +292,7 @@ public class VibrationHandler implements GameEventListener {
}
default boolean isValidVibration(GameEvent event, @Nullable Entity entity) {
if (!event.is(this.getListenableEvents())) {
if (!event.is(this.getListenableEvents())) {
return false;
} else {
if (entity != null) {
@ -206,8 +300,10 @@ public class VibrationHandler implements GameEventListener {
return false;
}
if (entity.isSteppingCarefully() && event.is(GameEventTags.IGNORE_VIBRATIONS_SNEAKING)) {
if (this.canTriggerAvoidVibration() && entity instanceof ServerPlayer player) {
if (entity.isSteppingCarefully()
&& event.is(GameEventTags.IGNORE_VIBRATIONS_SNEAKING)) {
if (this.canTriggerAvoidVibration()
&& entity instanceof ServerPlayer player) {
WBCriteriaTriggers.AVOID_VIBRATION.trigger(player);
}
@ -221,9 +317,23 @@ public class VibrationHandler implements GameEventListener {
}
}
boolean shouldListen(ServerLevel level, GameEventListener listener, BlockPos pos, GameEvent event, @Nullable Entity entity);
boolean shouldListen(
ServerLevel level,
GameEventListener listener,
BlockPos pos,
GameEvent event,
@Nullable Entity entity
);
void onSignalReceive(ServerLevel level, GameEventListener listener, BlockPos pos, GameEvent event, @Nullable Entity entity, @Nullable Entity source, float distance);
void onSignalReceive(
ServerLevel level,
GameEventListener listener,
BlockPos pos,
GameEvent event,
@Nullable Entity entity,
@Nullable Entity source,
float distance
);
default void onSignalSchedule() {}
}

View file

@ -1,5 +1,16 @@
package com.cursedcauldron.wildbackport.common.entities.warden;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.Random;
import java.util.UUID;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import javax.annotation.Nullable;
import com.google.common.collect.Streams;
import com.mojang.datafixers.util.Pair;
import com.mojang.serialization.Codec;
@ -15,23 +26,23 @@ import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.Random;
import java.util.UUID;
import java.util.function.Predicate;
import java.util.stream.Collectors;
//<>
public class WardenAngerManager {
private int updateTimer = Mth.randomBetweenInclusive(new Random(), 0, 2);
int primeAnger;
private static final Codec<Pair<UUID, Integer>> SUSPECT_CODEC = RecordCodecBuilder.create(instance -> instance.group(SerializableUUID.CODEC.fieldOf("uuid").forGetter(Pair::getFirst), ExtraCodecs.NON_NEGATIVE_INT.fieldOf("anger").forGetter(Pair::getSecond)).apply(instance, Pair::of));
private static final Codec<Pair<UUID, Integer>> SUSPECT_CODEC
= RecordCodecBuilder.create(
instance
-> instance
.group(
SerializableUUID.CODEC.fieldOf("uuid").forGetter(Pair::getFirst),
ExtraCodecs.NON_NEGATIVE_INT.fieldOf("anger").forGetter(
Pair::getSecond
)
)
.apply(instance, Pair::of)
);
private final Predicate<Entity> suspectPredicate;
protected final ArrayList<Entity> suspects;
private final SuspectComparator suspectComparator;
@ -39,20 +50,49 @@ public class WardenAngerManager {
protected final Object2IntMap<UUID> suspectUuidsToAngerLevel;
public static Codec<WardenAngerManager> codec(Predicate<Entity> validTarget) {
return RecordCodecBuilder.create(instance -> instance.group(SUSPECT_CODEC.listOf().fieldOf("suspects").orElse(Collections.emptyList()).forGetter(WardenAngerManager::getSuspects)).apply(instance, suspects -> new WardenAngerManager(validTarget, suspects)));
return RecordCodecBuilder.create(
instance
-> instance
.group(SUSPECT_CODEC.listOf()
.fieldOf("suspects")
.orElse(Collections.emptyList())
.forGetter(WardenAngerManager::getSuspects))
.apply(
instance, suspects -> new WardenAngerManager(validTarget, suspects)
)
);
}
public WardenAngerManager(Predicate<Entity> suspectPredicate, List<Pair<UUID, Integer>> suspectUuidsToAngerLevel) {
public WardenAngerManager(
Predicate<Entity> suspectPredicate,
List<Pair<UUID, Integer>> suspectUuidsToAngerLevel
) {
this.suspectPredicate = suspectPredicate;
this.suspects = new ArrayList<>();
this.suspectComparator = new SuspectComparator(this);
this.suspectsToAngerLevel = new Object2IntOpenHashMap<>();
this.suspectUuidsToAngerLevel = new Object2IntOpenHashMap<>(suspectUuidsToAngerLevel.size());
suspectUuidsToAngerLevel.forEach(suspect -> this.suspectUuidsToAngerLevel.put(suspect.getFirst(), suspect.getSecond()));
this.suspectUuidsToAngerLevel
= new Object2IntOpenHashMap<>(suspectUuidsToAngerLevel.size());
suspectUuidsToAngerLevel.forEach(
suspect
-> this.suspectUuidsToAngerLevel.put(suspect.getFirst(), suspect.getSecond())
);
}
private List<Pair<UUID, Integer>> getSuspects() {
return Streams.concat(this.suspects.stream().map(suspect -> Pair.of(suspect.getUUID(), this.suspectsToAngerLevel.getInt(suspect))), this.suspectUuidsToAngerLevel.object2IntEntrySet().stream().map(entry -> Pair.of(entry.getKey(), entry.getIntValue()))).collect(Collectors.toList());
return Streams
.concat(
this.suspects.stream().map(
suspect
-> Pair.of(
suspect.getUUID(), this.suspectsToAngerLevel.getInt(suspect)
)
),
this.suspectUuidsToAngerLevel.object2IntEntrySet().stream().map(
entry -> Pair.of(entry.getKey(), entry.getIntValue())
)
)
.collect(Collectors.toList());
}
public void tick(ServerLevel level, Predicate<Entity> suspectPredicate) {
@ -62,9 +102,10 @@ public class WardenAngerManager {
this.updateTimer = 2;
}
ObjectIterator<Object2IntMap.Entry<UUID>> uuidToAnger = this.suspectUuidsToAngerLevel.object2IntEntrySet().iterator();
ObjectIterator<Object2IntMap.Entry<UUID>> uuidToAnger
= this.suspectUuidsToAngerLevel.object2IntEntrySet().iterator();
while(uuidToAnger.hasNext()) {
while (uuidToAnger.hasNext()) {
Object2IntMap.Entry<UUID> entry = uuidToAnger.next();
int anger = entry.getIntValue();
if (anger <= 1) {
@ -74,9 +115,10 @@ public class WardenAngerManager {
}
}
ObjectIterator<Object2IntMap.Entry<Entity>> suspectToAnger = this.suspectsToAngerLevel.object2IntEntrySet().iterator();
ObjectIterator<Object2IntMap.Entry<Entity>> suspectToAnger
= this.suspectsToAngerLevel.object2IntEntrySet().iterator();
while(suspectToAnger.hasNext()) {
while (suspectToAnger.hasNext()) {
Object2IntMap.Entry<Entity> entry = suspectToAnger.next();
int anger = entry.getIntValue();
Entity entity = entry.getKey();
@ -121,57 +163,83 @@ public class WardenAngerManager {
public int increaseAngerAt(Entity entity, int amount) {
boolean isTarget = !this.suspectsToAngerLevel.containsKey(entity);
int angerLevel = this.suspectsToAngerLevel.computeInt(entity, (suspect, anger) -> Math.min(150, (anger == null ? 0 : anger) + amount));
if (isTarget) {
int modifier = this.suspectUuidsToAngerLevel.removeInt(entity.getUUID());
this.suspectsToAngerLevel.put(entity, angerLevel += modifier);
this.suspects.add(entity);
}
if (isTarget) {
int modifier = this.suspectUuidsToAngerLevel.removeInt(
entity.getUUID()
);
this.suspectsToAngerLevel.put(
entity, angerLevel += modifier
);
this.suspects.add(entity);
}
this.updatePrimeAnger();
return angerLevel;
}
public void removeSuspect(Entity entity) {
this.suspectsToAngerLevel.removeInt(entity);
this.suspects.remove(entity);
this.updatePrimeAnger();
}
@Nullable
private Entity getPrimeSuspectInternal() {
return this.suspects.stream().filter(this.suspectPredicate).findFirst().orElse(null);
}
public int getAngerFor(@Nullable Entity entity) {
return entity == null ? this.primeAnger : this.suspectsToAngerLevel.getInt(entity);
}
public Optional<LivingEntity> getPrimeSuspect() {
return Optional.ofNullable(this.getPrimeSuspectInternal()).filter(suspect -> suspect instanceof LivingEntity).map(suspect -> (LivingEntity)suspect);
}
protected record SuspectComparator(WardenAngerManager angerManagement) implements Comparator<Entity> {
public int compare(Entity firstSuspect, Entity secondSuspect) {
if (firstSuspect.equals(secondSuspect)) {
return 0;
} else {
int angerToFirstSuspect = this.angerManagement.suspectsToAngerLevel.getOrDefault(firstSuspect, 0);
int angerToSecondSuspect = this.angerManagement.suspectsToAngerLevel.getOrDefault(secondSuspect, 0);
this.angerManagement.primeAnger = Math.max(this.angerManagement.primeAnger, Math.max(angerToFirstSuspect, angerToSecondSuspect));
boolean isAngryWithFirstSuspect = Angriness.getForAnger(angerToFirstSuspect).isAngry();
boolean isAngryWithSecondSuspect = Angriness.getForAnger(angerToSecondSuspect).isAngry();
if (isAngryWithFirstSuspect != isAngryWithSecondSuspect) {
return isAngryWithFirstSuspect ? -1 : 1;
} else {
boolean isFirstSuspectPlayer = firstSuspect instanceof Player;
boolean isSecondSuspectPlayer = secondSuspect instanceof Player;
if (isFirstSuspectPlayer != isSecondSuspectPlayer) {
return isFirstSuspectPlayer ? -1 : 1;
} else {
return Integer.compare(angerToSecondSuspect, angerToFirstSuspect);
this.updatePrimeAnger();
return angerLevel;
}
}
}
}
}
}
public void removeSuspect(Entity entity) {
this.suspectsToAngerLevel.removeInt(entity);
this.suspects.remove(entity);
this.updatePrimeAnger();
}
@Nullable
private Entity getPrimeSuspectInternal() {
return this.suspects.stream()
.filter(this.suspectPredicate)
.findFirst()
.orElse(null);
}
public int getAngerFor(@Nullable Entity entity) {
return entity == null ? this.primeAnger
: this.suspectsToAngerLevel.getInt(entity);
}
public Optional<LivingEntity> getPrimeSuspect() {
return Optional.ofNullable(this.getPrimeSuspectInternal())
.filter(suspect -> suspect instanceof LivingEntity)
.map(suspect -> (LivingEntity) suspect);
}
protected record SuspectComparator(WardenAngerManager angerManagement)
implements Comparator<Entity> {
public int compare(Entity firstSuspect, Entity secondSuspect) {
if (firstSuspect.equals(secondSuspect)) {
return 0;
} else {
int angerToFirstSuspect
= this.angerManagement.suspectsToAngerLevel
.getOrDefault(firstSuspect, 0);
int angerToSecondSuspect
= this.angerManagement.suspectsToAngerLevel
.getOrDefault(secondSuspect, 0);
this.angerManagement.primeAnger = Math.max(
this.angerManagement.primeAnger,
Math.max(angerToFirstSuspect, angerToSecondSuspect)
);
boolean isAngryWithFirstSuspect
= Angriness.getForAnger(angerToFirstSuspect)
.isAngry();
boolean isAngryWithSecondSuspect
= Angriness.getForAnger(angerToSecondSuspect)
.isAngry();
if (isAngryWithFirstSuspect != isAngryWithSecondSuspect) {
return isAngryWithFirstSuspect ? -1 : 1;
} else {
boolean isFirstSuspectPlayer
= firstSuspect instanceof Player;
boolean isSecondSuspectPlayer
= secondSuspect instanceof Player;
if (isFirstSuspectPlayer != isSecondSuspectPlayer) {
return isFirstSuspectPlayer ? -1 : 1;
} else {
return Integer.compare(
angerToSecondSuspect, angerToFirstSuspect
);
}
}
}
}
}
}

View file

@ -1,5 +1,7 @@
package com.cursedcauldron.wildbackport.common.entities.warden;
import java.util.Optional;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.server.level.ServerLevel;
@ -10,20 +12,30 @@ import net.minecraft.world.entity.MobSpawnType;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import java.util.Optional;
public class WardenSpawnHelper {
public static <T extends Mob> Optional<T> trySpawnMob(EntityType<T> type, MobSpawnType spawnType, ServerLevel level, BlockPos pos, int tries, int xzRange, int yRange) {
public static <T extends Mob> Optional<T> trySpawnMob(
EntityType<T> type,
MobSpawnType spawnType,
ServerLevel level,
BlockPos pos,
int tries,
int xzRange,
int yRange
) {
BlockPos.MutableBlockPos mutable = pos.mutable();
for(int i = 0; i < tries; ++i) {
for (int i = 0; i < tries; ++i) {
int x = Mth.randomBetweenInclusive(level.random, -xzRange, xzRange);
int z = Mth.randomBetweenInclusive(level.random, -xzRange, xzRange);
mutable.setWithOffset(pos, x, yRange, z);
if (level.getWorldBorder().isWithinBounds(mutable) && moveToPossibleSpawnPosition(level, yRange, mutable)) {
T mob = type.create(level, null, null, null, mutable, spawnType, false, false);
if (level.getWorldBorder().isWithinBounds(mutable)
&& moveToPossibleSpawnPosition(level, yRange, mutable)) {
T mob = type.create(
level, null, null, null, mutable, spawnType, false, false
);
if (mob != null) {
if (mob.checkSpawnRules(level, spawnType) && mob.checkSpawnObstruction(level)) {
if (mob.checkSpawnRules(level, spawnType)
&& mob.checkSpawnObstruction(level)) {
level.addFreshEntityWithPassengers(mob);
return Optional.of(mob);
}
@ -36,11 +48,13 @@ public class WardenSpawnHelper {
return Optional.empty();
}
private static boolean moveToPossibleSpawnPosition(ServerLevel level, int yRange, BlockPos.MutableBlockPos pos) {
private static boolean moveToPossibleSpawnPosition(
ServerLevel level, int yRange, BlockPos.MutableBlockPos pos
) {
BlockPos.MutableBlockPos toPos = (new BlockPos.MutableBlockPos()).set(pos);
BlockState toState = level.getBlockState(toPos);
for(int i = yRange; i >= -yRange; --i) {
for (int i = yRange; i >= -yRange; --i) {
pos.move(Direction.DOWN);
toPos.setWithOffset(pos, Direction.UP);
BlockState state = level.getBlockState(pos);
@ -55,7 +69,14 @@ public class WardenSpawnHelper {
return false;
}
public static boolean canSpawnOn(ServerLevel level, BlockPos pos, BlockState state, BlockPos toPos, BlockState toState) {
return toState.getCollisionShape(level, toPos).isEmpty() && Block.isFaceFull(state.getCollisionShape(level, pos), Direction.UP);
public static boolean canSpawnOn(
ServerLevel level,
BlockPos pos,
BlockState state,
BlockPos toPos,
BlockState toState
) {
return toState.getCollisionShape(level, toPos).isEmpty()
&& Block.isFaceFull(state.getCollisionShape(level, pos), Direction.UP);
}
}

View file

@ -1,5 +1,11 @@
package com.cursedcauldron.wildbackport.common.entities.warden;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.OptionalInt;
import java.util.function.Predicate;
import com.cursedcauldron.wildbackport.common.entities.Warden;
import com.cursedcauldron.wildbackport.common.entities.access.WardenTracker;
import com.mojang.serialization.Codec;
@ -15,30 +21,34 @@ import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.Vec3;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.OptionalInt;
import java.util.function.Predicate;
//<>
public class WardenSpawnTracker {
public static final Codec<WardenSpawnTracker> CODEC = RecordCodecBuilder.create(instance -> {
return instance.group(ExtraCodecs.NON_NEGATIVE_INT.fieldOf("ticks_since_last_warning").orElse(0).forGetter(tracker -> {
return tracker.ticksSinceLastWarning;
}), ExtraCodecs.NON_NEGATIVE_INT.fieldOf("warning_level").orElse(0).forGetter(tracker -> {
return tracker.warningLevel;
}), ExtraCodecs.NON_NEGATIVE_INT.fieldOf("cooldown_ticks").orElse(0).forGetter(tracker -> {
return tracker.cooldownTicks;
})).apply(instance, WardenSpawnTracker::new);
});
public static final Codec<WardenSpawnTracker> CODEC = RecordCodecBuilder.create(
instance -> {
return instance
.group(
ExtraCodecs.NON_NEGATIVE_INT.fieldOf("ticks_since_last_warning")
.orElse(0)
.forGetter(tracker -> { return tracker.ticksSinceLastWarning; }),
ExtraCodecs.NON_NEGATIVE_INT.fieldOf("warning_level")
.orElse(0)
.forGetter(tracker -> { return tracker.warningLevel; }),
ExtraCodecs.NON_NEGATIVE_INT.fieldOf("cooldown_ticks")
.orElse(0)
.forGetter(tracker -> { return tracker.cooldownTicks; })
)
.apply(instance, WardenSpawnTracker::new);
}
);
private int ticksSinceLastWarning;
private int warningLevel;
private int cooldownTicks;
public WardenSpawnTracker(int ticksSinceLastWarning, int warningLevel, int cooldownTicks) {
public WardenSpawnTracker(
int ticksSinceLastWarning, int warningLevel, int cooldownTicks
) {
this.ticksSinceLastWarning = ticksSinceLastWarning;
this.warningLevel = warningLevel;
this.cooldownTicks = cooldownTicks;
@ -67,21 +77,31 @@ public class WardenSpawnTracker {
return this.cooldownTicks > 0;
}
public static OptionalInt tryWarn(ServerLevel level, BlockPos pos, ServerPlayer player) {
public static OptionalInt
tryWarn(ServerLevel level, BlockPos pos, ServerPlayer player) {
if (!hasNearbyWarden(level, pos)) {
List<ServerPlayer> players = getNearbyPlayers(level, pos);
if (!players.contains(player)) {
players.add(player);
}
if (players.stream().anyMatch(playerIn -> WardenTracker.of(playerIn).getWardenSpawnTracker().onCooldown())) {
if (players.stream().anyMatch(
playerIn
-> WardenTracker.of(playerIn).getWardenSpawnTracker().onCooldown()
)) {
return OptionalInt.empty();
}
Optional<WardenSpawnTracker> optional = players.stream().map(WardenTracker::getWardenSpawnTracker).max(Comparator.comparingInt(tracker -> tracker.warningLevel));
Optional<WardenSpawnTracker> optional
= players.stream()
.map(WardenTracker::getWardenSpawnTracker)
.max(Comparator.comparingInt(tracker -> tracker.warningLevel));
WardenSpawnTracker tracker = optional.get();
tracker.increaseWarningLevel();
players.forEach(playerIn -> WardenTracker.of(playerIn).getWardenSpawnTracker().copyData(tracker));
players.forEach(
playerIn
-> WardenTracker.of(playerIn).getWardenSpawnTracker().copyData(tracker)
);
return OptionalInt.of(tracker.warningLevel);
} else {
return OptionalInt.empty();
@ -95,8 +115,11 @@ public class WardenSpawnTracker {
private static List<ServerPlayer> getNearbyPlayers(ServerLevel level, BlockPos pos) {
Vec3 center = Vec3.atCenterOf(pos);
Predicate<ServerPlayer> predicate = player -> player.position().closerThan(center, 16.0D);
return level.getPlayers(predicate.and(LivingEntity::isAlive).and(EntitySelector.NO_SPECTATORS));
Predicate<ServerPlayer> predicate
= player -> player.position().closerThan(center, 16.0D);
return level.getPlayers(
predicate.and(LivingEntity::isAlive).and(EntitySelector.NO_SPECTATORS)
);
}
private void increaseWarningLevel() {

View file

@ -1,5 +1,8 @@
package com.cursedcauldron.wildbackport.common.items;
import java.util.List;
import java.util.function.Predicate;
import com.cursedcauldron.wildbackport.common.entities.ChestBoat;
import com.cursedcauldron.wildbackport.common.entities.MangroveBoat;
import net.minecraft.core.BlockPos;
@ -19,13 +22,11 @@ import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.HitResult;
import net.minecraft.world.phys.Vec3;
import java.util.List;
import java.util.function.Predicate;
//<>
public class ChestBoatItem extends Item {
private static final Predicate<Entity> RIDERS = EntitySelector.NO_SPECTATORS.and(Entity::isPickable);
private static final Predicate<Entity> RIDERS
= EntitySelector.NO_SPECTATORS.and(Entity::isPickable);
private final Boat.Type type;
private final boolean chested;
@ -36,19 +37,27 @@ public class ChestBoatItem extends Item {
}
@Override
public InteractionResultHolder<ItemStack> use(Level level, Player player, InteractionHand hand) {
public InteractionResultHolder<ItemStack>
use(Level level, Player player, InteractionHand hand) {
ItemStack stack = player.getItemInHand(hand);
HitResult hitResult = getPlayerPOVHitResult(level, player, ClipContext.Fluid.ANY);
if (hitResult.getType() == HitResult.Type.MISS) {
return InteractionResultHolder.pass(stack);
} else {
Vec3 viewVector = player.getViewVector(1.0F);
List<Entity> entities = level.getEntities(player, player.getBoundingBox().expandTowards(viewVector.scale(5.0D)).inflate(1.0D), RIDERS);
List<Entity> entities = level.getEntities(
player,
player.getBoundingBox()
.expandTowards(viewVector.scale(5.0D))
.inflate(1.0D),
RIDERS
);
if (!entities.isEmpty()) {
Vec3 eyePosition = player.getEyePosition();
for (Entity entity : entities) {
AABB box = entity.getBoundingBox().inflate(entity.getPickRadius());
if (box.contains(eyePosition)) return InteractionResultHolder.pass(stack);
if (box.contains(eyePosition))
return InteractionResultHolder.pass(stack);
}
}
@ -61,12 +70,19 @@ public class ChestBoatItem extends Item {
} else {
if (!level.isClientSide) {
level.addFreshEntity(boat);
level.gameEvent(player, GameEvent.ENTITY_PLACE, new BlockPos(hitResult.getLocation()));
if (!player.getAbilities().instabuild) stack.shrink(1);
level.gameEvent(
player,
GameEvent.ENTITY_PLACE,
new BlockPos(hitResult.getLocation())
);
if (!player.getAbilities().instabuild)
stack.shrink(1);
}
player.awardStat(Stats.ITEM_USED.get(this));
return InteractionResultHolder.sidedSuccess(stack, level.isClientSide);
return InteractionResultHolder.sidedSuccess(
stack, level.isClientSide
);
}
} else {
return InteractionResultHolder.pass(stack);

View file

@ -1,5 +1,7 @@
package com.cursedcauldron.wildbackport.common.items;
import javax.annotation.Nullable;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.client.renderer.item.ClampedItemPropertyFunction;
import net.minecraft.core.BlockPos;
@ -11,31 +13,43 @@ import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.phys.Vec3;
import javax.annotation.Nullable;
public class CompassItemPropertyFunction implements ClampedItemPropertyFunction {
private final CompassItemPropertyFunction.CompassWobble wobble = new CompassItemPropertyFunction.CompassWobble();
private final CompassItemPropertyFunction.CompassWobble wobbleRandom = new CompassItemPropertyFunction.CompassWobble();
private final CompassItemPropertyFunction.CompassWobble wobble
= new CompassItemPropertyFunction.CompassWobble();
private final CompassItemPropertyFunction.CompassWobble wobbleRandom
= new CompassItemPropertyFunction.CompassWobble();
public final CompassItemPropertyFunction.CompassTarget compassTarget;
public CompassItemPropertyFunction(CompassItemPropertyFunction.CompassTarget target) {
this.compassTarget = target;
}
public float unclampedCall(ItemStack p_234960_, @Nullable ClientLevel p_234961_, @Nullable LivingEntity p_234962_, int p_234963_) {
Entity entity = p_234962_ != null ? p_234962_ : p_234960_.getEntityRepresentation();
public float unclampedCall(
ItemStack p_234960_,
@Nullable ClientLevel p_234961_,
@Nullable LivingEntity p_234962_,
int p_234963_
) {
Entity entity
= p_234962_ != null ? p_234962_ : p_234960_.getEntityRepresentation();
if (entity == null) {
return 0.0F;
} else {
p_234961_ = this.tryFetchLevelIfMissing(entity, p_234961_);
return p_234961_ == null ? 0.0F : this.getCompassRotation(p_234960_, p_234961_, p_234963_, entity);
return p_234961_ == null
? 0.0F
: this.getCompassRotation(p_234960_, p_234961_, p_234963_, entity);
}
}
private float getCompassRotation(ItemStack p_234955_, ClientLevel p_234956_, int p_234957_, Entity p_234958_) {
private float getCompassRotation(
ItemStack p_234955_, ClientLevel p_234956_, int p_234957_, Entity p_234958_
) {
GlobalPos globalpos = this.compassTarget.getPos(p_234956_, p_234955_, p_234958_);
long i = p_234956_.getGameTime();
return !this.isValidCompassTargetPos(p_234958_, globalpos) ? this.getRandomlySpinningRotation(p_234957_, i) : this.getRotationTowardsCompassTarget(p_234958_, i, globalpos.pos());
return !this.isValidCompassTargetPos(p_234958_, globalpos)
? this.getRandomlySpinningRotation(p_234957_, i)
: this.getRotationTowardsCompassTarget(p_234958_, i, globalpos.pos());
}
private float getRandomlySpinningRotation(int p_234937_, long p_234938_) {
@ -43,11 +57,14 @@ public class CompassItemPropertyFunction implements ClampedItemPropertyFunction
this.wobbleRandom.update(p_234938_, Math.random());
}
double d0 = this.wobbleRandom.rotation + (double)((float)this.hash(p_234937_) / 2.14748365E9F);
return Mth.positiveModulo((float)d0, 1.0F);
double d0 = this.wobbleRandom.rotation
+ (double) ((float) this.hash(p_234937_) / 2.14748365E9F);
return Mth.positiveModulo((float) d0, 1.0F);
}
private float getRotationTowardsCompassTarget(Entity p_234942_, long p_234943_, BlockPos p_234944_) {
private float getRotationTowardsCompassTarget(
Entity p_234942_, long p_234943_, BlockPos p_234944_
) {
double d0 = this.getAngleFromEntityToPos(p_234942_, p_234944_);
double d1 = this.getWrappedVisualRotationY(p_234942_);
if (p_234942_ instanceof Player player) {
@ -57,26 +74,35 @@ public class CompassItemPropertyFunction implements ClampedItemPropertyFunction
}
double d3 = d0 + this.wobble.rotation;
return Mth.positiveModulo((float)d3, 1.0F);
return Mth.positiveModulo((float) d3, 1.0F);
}
}
double d2 = 0.5D - (d1 - 0.25D - d0);
return Mth.positiveModulo((float)d2, 1.0F);
return Mth.positiveModulo((float) d2, 1.0F);
}
@javax.annotation.Nullable
private ClientLevel tryFetchLevelIfMissing(Entity p_234946_, @javax.annotation.Nullable ClientLevel p_234947_) {
return p_234947_ == null && p_234946_.level instanceof ClientLevel ? (ClientLevel)p_234946_.level : p_234947_;
private ClientLevel tryFetchLevelIfMissing(
Entity p_234946_, @javax.annotation.Nullable ClientLevel p_234947_
) {
return p_234947_ == null && p_234946_.level instanceof ClientLevel
? (ClientLevel) p_234946_.level
: p_234947_;
}
private boolean isValidCompassTargetPos(Entity p_234952_, @javax.annotation.Nullable GlobalPos p_234953_) {
return p_234953_ != null && p_234953_.dimension() == p_234952_.level.dimension() && !(p_234953_.pos().distToCenterSqr(p_234952_.position()) < (double)1.0E-5F);
private boolean isValidCompassTargetPos(
Entity p_234952_, @javax.annotation.Nullable GlobalPos p_234953_
) {
return p_234953_ != null && p_234953_.dimension() == p_234952_.level.dimension()
&& !(p_234953_.pos().distToCenterSqr(p_234952_.position()) < (double) 1.0E-5F
);
}
private double getAngleFromEntityToPos(Entity p_234949_, BlockPos p_234950_) {
Vec3 vec3 = Vec3.atCenterOf(p_234950_);
return Math.atan2(vec3.z() - p_234949_.getZ(), vec3.x() - p_234949_.getX()) / (double)((float)Math.PI * 2F);
return Math.atan2(vec3.z() - p_234949_.getZ(), vec3.x() - p_234949_.getX())
/ (double) ((float) Math.PI * 2F);
}
private double getWrappedVisualRotationY(Entity entity) {
@ -88,7 +114,8 @@ public class CompassItemPropertyFunction implements ClampedItemPropertyFunction
}
public interface CompassTarget {
@Nullable GlobalPos getPos(ClientLevel level, ItemStack stack, Entity entity);
@Nullable
GlobalPos getPos(ClientLevel level, ItemStack stack, Entity entity);
}
static class CompassWobble {

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