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