chore: format code
This commit is contained in:
parent
5a52058f3d
commit
d683e61c98
130
.clang-format
Normal file
130
.clang-format
Normal 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"]
|
|
@ -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;
|
||||
// }));
|
||||
}
|
||||
}
|
|
@ -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 it is too large
Load diff
File diff suppressed because one or more lines are too long
|
@ -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)
|
||||
);
|
||||
}
|
||||
}
|
|
@ -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
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) {}
|
|
@ -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
|
||||
);
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
});
|
||||
);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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"
|
||||
);
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
);
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -11,6 +11,6 @@ public interface WardenTracker {
|
|||
}
|
||||
|
||||
static WardenTracker of(Player player) {
|
||||
return (WardenTracker)player;
|
||||
return (WardenTracker) player;
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
);
|
||||
}
|
||||
}
|
|
@ -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
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
);
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
|
|
|
@ -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 }
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
);
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
);
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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() {}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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() {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
Loading…
Reference in a new issue