Inspired by 2020's April Fools' 20w14infinite Snapshot, this mod brings endless randomly generated dimensions into Minecraft.
1package net.lerariemann.infinity.entity.custom;
2
3import net.lerariemann.infinity.InfinityMod;
4import net.lerariemann.infinity.iridescence.Iridescence;
5import net.lerariemann.infinity.util.InfinityMethods;
6import net.lerariemann.infinity.util.VersionMethods;
7import net.lerariemann.infinity.util.core.ConfigType;
8import net.lerariemann.infinity.util.core.NbtUtils;
9import net.lerariemann.infinity.util.core.RandomProvider;
10//? if >1.21 {
11import net.minecraft.MethodsReturnNonnullByDefault;
12import net.minecraft.core.component.DataComponentMap;
13import net.minecraft.core.component.DataComponents;
14import net.minecraft.network.codec.ByteBufCodecs;
15//?}
16import net.minecraft.core.registries.Registries;
17import net.minecraft.nbt.CompoundTag;
18import net.minecraft.network.chat.Component;
19import net.minecraft.network.syncher.EntityDataAccessor;
20import net.minecraft.network.syncher.EntityDataSerializer;
21import net.minecraft.network.syncher.EntityDataSerializers;
22import net.minecraft.network.syncher.SynchedEntityData;
23import net.minecraft.resources.ResourceKey;
24import net.minecraft.resources.ResourceLocation;
25import net.minecraft.server.level.ServerLevel;
26import net.minecraft.world.*;
27import net.minecraft.world.damagesource.DamageSource;
28import net.minecraft.world.entity.EntityType;
29import net.minecraft.world.entity.SpawnGroupData;
30import net.minecraft.world.entity.ai.attributes.AttributeSupplier;
31import net.minecraft.world.entity.ai.attributes.Attributes;
32import net.minecraft.world.entity.ai.goal.EatBlockGoal;
33import net.minecraft.world.entity.monster.Monster;
34import net.minecraft.world.item.ItemStack;
35import net.minecraft.world.level.Level;
36import net.minecraft.world.level.ServerLevelAccessor;
37import net.minecraft.world.level.block.Blocks;
38import net.minecraft.world.level.block.state.BlockState;
39//? if >1.21.4 {
40import net.minecraft.world.level.storage.ValueInput;
41import net.minecraft.world.level.storage.ValueOutput;
42//?}
43import net.minecraft.world.level.storage.loot.LootTable;
44import org.jetbrains.annotations.Nullable;
45
46//? if neoforge {
47/*import javax.annotation.ParametersAreNonnullByDefault;
48*///?}
49import java.util.*;
50import java.util.function.Supplier;
51
52//? if neoforge {
53/*@MethodsReturnNonnullByDefault
54@ParametersAreNonnullByDefault
55*///?}
56public class ChaosPawn extends AbstractChessFigure {
57
58 public static final EntityDataAccessor<CompoundTag> colors = SynchedEntityData.defineId(ChaosPawn.class, EntityDataSerializers.COMPOUND_TAG);
59 public static final EntityDataAccessor<Integer> special_case = SynchedEntityData.defineId(ChaosPawn.class, EntityDataSerializers.INT);
60
61 public ChaosPawn(EntityType<? extends ChaosPawn> entityType, Level world) {
62 super(entityType, world);
63 }
64 public void setColors(CompoundTag i) {
65 this.entityData.set(colors, i);
66 }
67 public CompoundTag getColors() {
68 return this.entityData.get(colors);
69 }
70
71 public static AttributeSupplier.Builder createAttributes() {
72 return Monster.createMonsterAttributes().add(Attributes.ATTACK_DAMAGE, 5.0)
73 .add(Attributes.FOLLOW_RANGE, 35.0)
74 //? if >1.21
75 .add(Attributes.SCALE, 0.9)
76 .add(Attributes.MOVEMENT_SPEED, 0.25F);
77 }
78 @Override
79 protected void defineSynchedData(
80 //? if >1.21 {
81 SynchedEntityData.Builder builder
82 //?}
83 ) {
84 super.defineSynchedData(
85 //? if >1.21 {
86 builder
87 //?}
88 );
89 //? if <1.21 {
90 /*var builder = this.entityData;
91 *///?}
92 builder.define(colors, new CompoundTag());
93 builder.define(special_case, -1);
94 }
95 @Override
96 protected void registerGoals() {
97 super.registerGoals();
98 this.goalSelector.addGoal(5, new EatBlockGoal(this));
99 }
100
101 @Override
102 public void ate() {
103 super.ate();
104 this.setAllColors(this.level().getBiome(this.blockPosition()).value().getGrassColor(this.getX(), this.getZ()));
105 }
106
107 @Override
108 public Component getTypeName() {
109 int i = getCase();
110 return switch (i) {
111 case 0 -> Component.translatable("entity.infinity.pawn_black");
112 case 1 -> Component.translatable("entity.infinity.pawn_white");
113 default -> super.getTypeName();
114 };
115 }
116
117 public int getCase() {
118 return entityData.get(special_case);
119 }
120
121 @Override
122 public void addAdditionalSaveData(
123 //? if >1.21.2 {
124 ValueOutput
125 //?} else {
126 /*CompoundTag
127 *///?}
128 nbt) {
129 super.addAdditionalSaveData(nbt);
130 //? if >1.21.4 {
131 NbtUtils.putColors(nbt, "colors", getColors());
132 //?} else {
133 /*nbt.put("colors", getColors());
134 *///?}
135 nbt.putInt("case", getCase());
136 }
137 @Override
138 public void readAdditionalSaveData(
139 //? if >1.21.2 {
140 ValueInput
141 //?} else {
142 /*CompoundTag
143 *///?}
144 nbt) {
145 super.readAdditionalSaveData(nbt);
146 //? if >1.21.4 {
147 this.setColors(NbtUtils.getColors(nbt, "colors"));
148 //?} else {
149 /*this.setColors(nbt.getCompound("colors"));
150 *///?}
151 this.entityData.set(special_case, NbtUtils.getInt(nbt, "case"));
152 }
153
154// @Override
155 public
156 //? if >1.21 {
157 ResourceKey<LootTable>
158 //?} else {
159 /*ResourceLocation
160 *///?}
161 getDefaultLootTable() {
162 ResourceLocation i = switch (getCase()) {
163 case 0 -> InfinityMethods.getId("entities/chaos_pawn_black");
164 case 1 -> InfinityMethods.getId("entities/chaos_pawn_white");
165 default -> {
166 boolean bl = RandomProvider.rule("pawnsCanDropIllegalItems");
167 if (bl) yield VersionMethods.id(""); //loot is defined in dropEquipment instead
168 else yield VersionMethods.id(InfinityMod.provider.randomName(random, ConfigType.LOOT_TABLES));
169 }
170 };
171 //? if >1.21 {
172 return ResourceKey.create(Registries.LOOT_TABLE, i);
173 //?} else {
174 /*return i;
175 *///?}
176 }
177
178 public static CompoundTag getColorSetup(Supplier<Integer> colorSupplier) {
179 CompoundTag c = new CompoundTag();
180 Arrays.stream((new String[]{"body", "left_arm", "right_arm", "left_leg", "right_leg"})).forEach(
181 s -> c.putInt(s, colorSupplier.get()));
182 int head = colorSupplier.get();
183 c.putInt("head", head);
184 c.putInt("hat", 0xFFFFFF ^ head);
185 return c;
186 }
187
188 public void setAllColors(int color) {
189 this.setColors(getColorSetup(() -> color));
190 }
191
192 @Override
193 public boolean isBlackOrWhite() {
194 return entityData.get(special_case) != -1 && !Iridescence.isUnderEffect(this);
195 }
196
197 public void initFromBlock(BlockState state) {
198 if (state.is(Blocks.WHITE_WOOL) || state.is(Blocks.WHITE_CONCRETE)) {
199 chess(true);
200 }
201 else if (state.is(Blocks.BLACK_WOOL) || state.is(Blocks.BLACK_CONCRETE)) {
202 chess(false);
203 }
204 else unchess();
205 }
206
207 public void chess(boolean white) {
208 entityData.set(special_case, white ? 1 : 0);
209 setAllColors(white ? 0xFFFFFF : 0);
210 }
211
212 public void unchess() {
213 entityData.set(special_case, -1);
214 setColors(getColorSetup(() -> random.nextInt(16777216)));
215 }
216
217 @Override
218 @Nullable
219 public SpawnGroupData finalizeSpawn(ServerLevelAccessor world, DifficultyInstance difficulty,
220
221 //? if >1.21.2 {
222 net.minecraft.world.entity.EntitySpawnReason
223 //?} else {
224 /*net.minecraft.world.entity.MobSpawnType
225 *///?}
226 spawnReason, @Nullable SpawnGroupData entityData
227 //? if <1.21 {
228 /*,CompoundTag tag
229 *///?}
230 ) {
231 initFromBlock(world.getBlockState(this.blockPosition().below()));
232 double i = random.nextDouble() * 40;
233 Objects.requireNonNull(this.getAttribute(Attributes.MAX_HEALTH)).setBaseValue(i);
234 this.setHealth((float)i);
235 return super.finalizeSpawn(world, difficulty, spawnReason, entityData
236 //? if <1.21
237 /*,tag*/
238 );
239 }
240
241 //? if >1.21 {
242 @Override
243 protected void dropCustomDeathLoot(ServerLevel world, DamageSource source, boolean causedByPlayer) {
244 super.dropCustomDeathLoot(world, source, causedByPlayer);
245 //?} else {
246 /*@Override
247 protected void dropCustomDeathLoot(DamageSource source, int lootingMultiplier, boolean allowDrops) {
248 super.dropCustomDeathLoot(source, lootingMultiplier, allowDrops);
249 *///?}
250 dropLootInternal();
251 }
252
253 protected void dropLootInternal() {
254 if (!this.isBlackOrWhite() && RandomProvider.rule("pawnsCanDropIllegalItems")) {
255 String s = InfinityMod.provider.randomName(random, ConfigType.ITEMS);
256 double i = Objects.requireNonNull(this.getAttribute(Attributes.MAX_HEALTH)).getBaseValue() / 10;
257 ItemStack stack = VersionMethods.getItem(s).getDefaultInstance().copyWithCount((int) (i * i));
258 //? if >1.21 {
259 stack.applyComponents(DataComponentMap.builder().set(DataComponents.MAX_STACK_SIZE, 64).build());
260 //?}
261 this.spawnAtLocation(
262 //? if >1.21.2 {
263 (ServerLevel) this.level(),
264 //?}
265 stack);
266 }
267 }
268}