1
1
package galena .oreganized .content .entity ;
2
2
3
+ import galena .oreganized .Oreganized ;
3
4
import galena .oreganized .content .block .GargoyleBlock ;
4
5
import galena .oreganized .index .OBlockEntities ;
5
6
import galena .oreganized .index .OParticleTypes ;
9
10
import galena .oreganized .network .packet .GargoyleParticlePacket ;
10
11
import galena .oreganized .world .ScaredOfGargoyleGoal ;
11
12
import net .minecraft .core .BlockPos ;
13
+ import net .minecraft .core .particles .ParticleOptions ;
14
+ import net .minecraft .core .particles .ParticleTypes ;
12
15
import net .minecraft .nbt .CompoundTag ;
13
16
import net .minecraft .nbt .NbtUtils ;
14
17
import net .minecraft .sounds .SoundSource ;
15
18
import net .minecraft .util .ParticleUtils ;
16
19
import net .minecraft .util .valueproviders .UniformInt ;
17
20
import net .minecraft .world .InteractionResult ;
21
+ import net .minecraft .world .entity .Entity ;
22
+ import net .minecraft .world .entity .LivingEntity ;
18
23
import net .minecraft .world .entity .Mob ;
19
24
import net .minecraft .world .entity .MobType ;
20
25
import net .minecraft .world .entity .player .Player ;
21
26
import net .minecraft .world .item .ItemStack ;
22
27
import net .minecraft .world .level .Level ;
28
+ import net .minecraft .world .level .block .Block ;
23
29
import net .minecraft .world .level .block .entity .BlockEntity ;
24
30
import net .minecraft .world .level .block .state .BlockState ;
25
31
import net .minecraft .world .phys .AABB ;
26
32
import net .minecraft .world .phys .Vec3 ;
27
33
import net .minecraftforge .network .PacketDistributor ;
34
+ import org .checkerframework .checker .units .qual .C ;
28
35
import org .jetbrains .annotations .Nullable ;
29
36
30
37
import java .util .Collection ;
31
38
32
39
public class GargoyleBlockEntity extends BlockEntity {
33
40
34
41
private static final int COOLDOWN = 20 * 30 ;
42
+ public static final String GROWL_COOLDOWN_TAG = Oreganized .MOD_ID + ":gargoyle_use_cooldown" ;
35
43
36
44
private int outputSignal = 0 ;
37
45
private int updateCooldown = 0 ;
38
46
private int growlCooldown = 0 ;
39
47
48
+ private ParticleOptions drippingFluid ;
49
+
40
50
public GargoyleBlockEntity (BlockPos pos , BlockState state ) {
41
51
super (OBlockEntities .GARGOYLE .get (), pos , state );
42
52
}
@@ -48,8 +58,15 @@ private static Collection<Mob> getTargets(Level level, BlockPos pos) {
48
58
49
59
public static void tick (Level level , BlockPos pos , BlockState state , GargoyleBlockEntity be ) {
50
60
be .growlCooldown --;
61
+
62
+ if (be .updateCooldown % 2 == 0 && be .drippingFluid != null ) {
63
+ GargoyleBlock .dripParticles (state , level , pos , level .random , be .drippingFluid );
64
+ }
65
+
51
66
if (--be .updateCooldown > 0 ) return ;
52
67
68
+ be .updateDripParticles (level , pos , state );
69
+
53
70
var targets = getTargets (level , pos );
54
71
var vec = Vec3 .atCenterOf (pos );
55
72
var closestDistance = targets .stream ()
@@ -70,6 +87,24 @@ public static void tick(Level level, BlockPos pos, BlockState state, GargoyleBlo
70
87
be .updateCooldown = 10 ;
71
88
}
72
89
90
+ private void updateDripParticles (Level level , BlockPos pos , BlockState state ) {
91
+ for (int i = 1 ; i <= 2 ; i ++) {
92
+ var targetPos = pos .below (i );
93
+ var targetState = level .getBlockState (targetPos );
94
+ var fluid = targetState .getFluidState ();
95
+ if (!fluid .isEmpty ()) {
96
+ drippingFluid = fluid .getDripParticle ();
97
+ return ;
98
+ }
99
+ }
100
+
101
+ if (level .isRainingAt (pos .above ())) {
102
+ drippingFluid = ParticleTypes .DRIPPING_DRIPSTONE_WATER ;
103
+ } else {
104
+ drippingFluid = null ;
105
+ }
106
+ }
107
+
73
108
public int getAnalogOutputSignal () {
74
109
return outputSignal ;
75
110
}
@@ -88,6 +123,7 @@ public void load(CompoundTag tag) {
88
123
89
124
public InteractionResult interact (Level level , BlockPos pos , @ Nullable Player player , ItemStack stack , boolean simulate ) {
90
125
if (growlCooldown > 0 ) return InteractionResult .PASS ;
126
+ if (player != null && player .getPersistentData ().getInt (GROWL_COOLDOWN_TAG ) > 0 ) return InteractionResult .PASS ;
91
127
if (!stack .is (OTags .Items .GARGOYLE_SNACK )) return InteractionResult .PASS ;
92
128
93
129
if (player == null || !player .getAbilities ().instabuild ) {
@@ -96,13 +132,14 @@ public InteractionResult interact(Level level, BlockPos pos, @Nullable Player pl
96
132
97
133
if (simulate ) return InteractionResult .SUCCESS ;
98
134
99
- getTargets (level , pos ).forEach (mob -> {
100
- mob .getPersistentData ().put (ScaredOfGargoyleGoal .AVOID_TAG_KEY , NbtUtils .writeBlockPos (pos ));
101
- });
135
+ getTargets (level , pos ).forEach (mob -> scare (mob , pos ));
102
136
103
137
level .playSound (null , pos .getX (), pos .getY (), pos .getZ (), OSoundEvents .GARGOYLE_GROWL .get (), SoundSource .BLOCKS , 1.0F , 1.0F );
104
138
105
139
growlCooldown = COOLDOWN ;
140
+ if (player != null && !player .getAbilities ().instabuild ) {
141
+ player .getPersistentData ().putInt (GROWL_COOLDOWN_TAG , COOLDOWN );
142
+ }
106
143
107
144
if (!level .isClientSide ) {
108
145
OreganizedNetwork .CHANNEL .send (PacketDistributor .DIMENSION .with (level ::dimension ), new GargoyleParticlePacket (pos ));
@@ -111,6 +148,15 @@ public InteractionResult interact(Level level, BlockPos pos, @Nullable Player pl
111
148
return InteractionResult .SUCCESS ;
112
149
}
113
150
151
+ private void scare (Entity mob , BlockPos pos ) {
152
+ var offset = mob .position ().subtract (pos .getX (), pos .getY (), pos .getZ ());
153
+ if (offset .length () < 4 ) {
154
+ var motion = offset .multiply (0.4 , 0.2 , 0.4 );
155
+ mob .push (motion .x , motion .y , motion .z );
156
+ }
157
+ mob .getPersistentData ().put (ScaredOfGargoyleGoal .AVOID_TAG_KEY , NbtUtils .writeBlockPos (pos ));
158
+ }
159
+
114
160
public void spawnParticles () {
115
161
var pos = getBlockPos ();
116
162
var state = getBlockState ();
0 commit comments