Inspired by 2020's April Fools' 20w14infinite Snapshot, this mod brings endless randomly generated dimensions into Minecraft.
at master 306 lines 14 kB view raw
1package net.lerariemann.infinity.entity.custom; 2 3import net.lerariemann.infinity.InfinityMod; 4import net.lerariemann.infinity.registry.core.ModEntities; 5import net.lerariemann.infinity.util.VersionMethods; 6import net.lerariemann.infinity.util.core.ConfigType; 7import net.lerariemann.infinity.util.core.NbtUtils; 8import net.lerariemann.infinity.util.platform.InfinityPlatform; 9import net.minecraft.core.Holder; 10import net.minecraft.core.particles.ParticleTypes; 11import net.minecraft.core.registries.BuiltInRegistries; 12import net.minecraft.core.registries.Registries; 13import net.minecraft.nbt.CompoundTag; 14import net.minecraft.network.chat.Component; 15import net.minecraft.network.syncher.EntityDataAccessor; 16import net.minecraft.network.syncher.EntityDataSerializers; 17import net.minecraft.network.syncher.SynchedEntityData; 18import net.minecraft.server.level.ServerLevel; 19import net.minecraft.sounds.SoundEvents; 20import net.minecraft.world.DifficultyInstance; 21import net.minecraft.world.InteractionHand; 22import net.minecraft.world.InteractionResult; 23import net.minecraft.world.damagesource.DamageSource; 24import net.minecraft.world.effect.MobEffect; 25import net.minecraft.world.effect.MobEffectInstance; 26import net.minecraft.world.entity.EntityType; 27import net.minecraft.world.entity.LivingEntity; 28import net.minecraft.world.entity.SpawnGroupData; 29import net.minecraft.world.entity.monster.Skeleton; 30import net.minecraft.world.entity.player.Player; 31import net.minecraft.world.item.ItemStack; 32import net.minecraft.world.item.ItemUtils; 33import net.minecraft.world.item.Items; 34//? if >1.21 { 35import net.minecraft.world.item.alchemy.PotionContents; 36import net.minecraft.core.component.DataComponents; 37//?} else { 38/*import net.minecraft.world.item.alchemy.PotionUtils; 39*///?} 40import net.minecraft.world.item.enchantment.Enchantment; 41import net.minecraft.world.item.enchantment.Enchantments; 42import net.minecraft.world.level.Level; 43import net.minecraft.world.level.ServerLevelAccessor; 44//? if >1.21.4 { 45import net.minecraft.world.level.storage.ValueInput; 46import net.minecraft.world.level.storage.ValueOutput; 47import static net.minecraft.world.entity.EntitySpawnReason.CONVERSION; 48import net.minecraft.client.resources.language.I18n; 49//?} 50import org.jspecify.annotations.Nullable; 51 52import java.util.*; 53 54public class ChaosSkeleton extends Skeleton implements TintableEntity { 55 private static final EntityDataAccessor<String> effect = SynchedEntityData.defineId(ChaosSkeleton.class, EntityDataSerializers.STRING); 56 private static final EntityDataAccessor<Integer> color = SynchedEntityData.defineId(ChaosSkeleton.class, EntityDataSerializers.INT); 57 private static final EntityDataAccessor<Integer> duration = SynchedEntityData.defineId(ChaosSkeleton.class, EntityDataSerializers.INT); 58 public static Map<String, String> effect_lookup = Map.ofEntries(Map.entry("minecraft:unluck", "minecraft:luck"), 59 Map.entry("minecraft:bad_omen", "minecraft:hero_of_the_village"), 60 Map.entry("minecraft:darkness", "minecraft:night_vision"), 61 Map.entry("minecraft:blindness", "minecraft:night_vision"), 62 Map.entry("minecraft:glowing", "minecraft:invisibility"), 63 Map.entry("minecraft:hunger", "minecraft:saturation"), 64 Map.entry("minecraft:levitation", "minecraft:slow_falling"), 65 Map.entry("minecraft:mining_fatigue", "minecraft:haste"), 66 Map.entry("minecraft:poison", "minecraft:regeneration"), 67 Map.entry("minecraft:slowness", "minecraft:speed"), 68 Map.entry("minecraft:weakness", "minecraft:strength"), 69 Map.entry("minecraft:wither", "minecraft:regeneration"), 70 Map.entry("minecraft:instant_damage", "minecraft:instant_health"), 71 Map.entry("minecraft:instant_health", "minecraft:instant_damage"), 72 Map.entry("minecraft:luck", "minecraft:unluck"), 73 Map.entry("minecraft:hero_of_the_village", "minecraft:bad_omen"), 74 Map.entry("minecraft:night_vision", "minecraft:darkness"), 75 Map.entry("minecraft:invisibility", "minecraft:glowing"), 76 Map.entry("minecraft:saturation", "minecraft:hunger"), 77 Map.entry("minecraft:slow_falling", "minecraft:levitation"), 78 Map.entry("minecraft:haste", "minecraft:mining_fatigue"), 79 Map.entry("minecraft:regeneration", "minecraft:poison"), 80 Map.entry("minecraft:speed", "minecraft:slowness"), 81 Map.entry("minecraft:strength", "minecraft:weakness")); 82 83 public ChaosSkeleton(EntityType<? extends Skeleton> entityType, Level world) { 84 super(entityType, world); 85 } 86 87 @Override 88 public int getColorNamed() { 89 return hasCustomName() ? TintableEntity.getColorNamed(getName().getString(), tickCount, getId()) : -1; 90 } 91 92 @Override 93 @Nullable 94 public SpawnGroupData finalizeSpawn(ServerLevelAccessor world, DifficultyInstance difficulty, 95 //? if >1.21.2 { 96 net.minecraft.world.entity.EntitySpawnReason 97 //?} else { 98 /*net.minecraft.world.entity.MobSpawnType 99 *///?} 100 spawnReason, @Nullable SpawnGroupData entityData 101 //? if <1.21 { 102 /*,CompoundTag tag 103 *///?} 104 ) { 105 Random r = new Random(); 106 CompoundTag effect = InfinityMod.provider.randomElement(r, ConfigType.EFFECTS); 107 this.setEffect(effect); 108 this.setDuration(r.nextInt(600)); 109 return super.finalizeSpawn(world, difficulty, spawnReason, entityData 110 //? if <1.21 111 /*,tag*/ 112 ); 113 } 114 115 @Override 116 protected void defineSynchedData( 117 //? if >1.21 { 118 SynchedEntityData.Builder builder 119 //?} 120 ) { 121 super.defineSynchedData( 122 //? if >1.21 { 123 builder 124 //?} 125 ); 126 //? if <1.21 { 127 /*var builder = this.entityData; 128 *///?} 129 builder.define(effect, "luck"); 130 builder.define(duration, 200); 131 builder.define(color, 0x00FF00); 132 } 133 @Override 134 public boolean isSunBurnTick() { 135 return false; 136 } 137 138 @Override 139 public InteractionResult mobInteract(Player player, InteractionHand hand) { 140 ItemStack itemStack = player.getItemInHand(hand); 141 if (itemStack.is(Items.FERMENTED_SPIDER_EYE) && effect_lookup.containsKey(this.getEffect())) { 142 if (!player.getAbilities().instabuild) { 143 itemStack.shrink(1); 144 } 145 if (player.level().getRandom().nextFloat() < 0.5) { 146 String i = effect_lookup.get(this.getEffect()); 147 MobEffect newEffect = VersionMethods.getFromRegistry(BuiltInRegistries.MOB_EFFECT, VersionMethods.id(i)); 148 if (newEffect != null) { 149 ChaosSkeleton newSkeleton; 150 if (!this.level().isClientSide() && (newSkeleton = ModEntities.CHAOS_SKELETON.get().create(this.level() 151 //? if >1.21.4 { 152 ,CONVERSION 153 //?} 154 )) != null) { 155 ((ServerLevel) this.level()).sendParticles(ParticleTypes.HEART, this.getX(), this.getY(0.5), this.getZ(), 1, 0.0, 0.0, 0.0, 0.0); 156 this.discard(); 157 ModEntities.copy(this, newSkeleton); 158 newSkeleton.setDuration(this.getDuration()); 159 newSkeleton.setEffect(i, newEffect.getColor()); 160 this.level().addFreshEntity(newSkeleton); 161 return InteractionResult.SUCCESS; 162 } 163 } 164 } 165 } 166 if (itemStack.is(Items.GLASS_BOTTLE)) { 167 ItemStack itemStack2 = setPotion(Items.POTION.getDefaultInstance(), this.getColorForRender(), this.getEffect(), this.getDuration() * 20); 168 ItemStack itemStack3 = ItemUtils.createFilledResult(itemStack, player, itemStack2, false); 169 player.setItemInHand(hand, itemStack3); 170 this.playSound(SoundEvents.BOTTLE_FILL, 1.0f, 1.0f); 171 Skeleton newSkeleton; 172 if (!this.level().isClientSide() && (newSkeleton = EntityType.SKELETON.create(this.level() 173 //? if >1.21.4 { 174 , CONVERSION 175 //?} 176 )) != null) { 177 this.discard(); 178 ModEntities.copy(this, newSkeleton); 179 this.level().addFreshEntity(newSkeleton); 180 return InteractionResult.SUCCESS; 181 } 182 } 183 return super.mobInteract(player, hand); 184 } 185 186 public void setEffect(CompoundTag eff) { 187 setEffect(NbtUtils.getString(eff, "Name"), NbtUtils.getInt(eff, "Color")); 188 } 189 public void setEffect(String eff, int c) { 190 if (eff.isBlank()) { 191 CompoundTag newEffect = InfinityMod.provider.randomElement(random, ConfigType.EFFECTS); 192 eff = NbtUtils.getString(newEffect, "Name"); 193 c = NbtUtils.getInt(newEffect, "Color"); 194 } 195 this.entityData.set(effect, eff); 196 this.entityData.set(color, c); 197 } 198 public String getEffect() { 199 return this.entityData.get(effect); 200 } 201 @Override 202 public int getColor() { 203 return this.entityData.get(color); 204 } 205 206 public void setDuration(int i) { 207 this.entityData.set(duration, i); 208 } 209 public int getDuration() { 210 return this.entityData.get(duration); 211 } 212 //? if >1.21.4 { 213 214 @Override 215 protected void addAdditionalSaveData(ValueOutput output) { 216 super.addAdditionalSaveData(output); 217 output.putString("effect", this.getEffect()); 218 output.putInt("duration", this.getDuration()); 219 output.putInt("color", this.getColor()); 220 } 221 222 //?} else { 223 /*@Override 224 public void addAdditionalSaveData(CompoundTag nbt) { 225 super.addAdditionalSaveData(nbt); 226 nbt.putString("effect", this.getEffect()); 227 nbt.putInt("duration", this.getDuration()); 228 nbt.putInt("color", this.getColor()); 229 } 230 *///?} 231 232 @Override 233 public void readAdditionalSaveData( 234 //? if >1.21.2 { 235 ValueInput 236 //?} else { 237 /*CompoundTag 238 *///?} 239 nbt) { 240 super.readAdditionalSaveData(nbt); 241 this.setEffect(NbtUtils.getString(nbt, "effect"), NbtUtils.getInt(nbt, "color")); 242 this.setDuration(NbtUtils.getInt(nbt,"duration")); 243 } 244 245 public static ItemStack setPotion(ItemStack stack, int color, String effect, int duration) { 246 List<MobEffectInstance> customEffects = new ArrayList<>(); 247 //? if >1.21.4 { 248 customEffects.add(new MobEffectInstance(VersionMethods.getFromId(BuiltInRegistries.MOB_EFFECT, VersionMethods.id(effect)), duration)); 249 //?} else { 250 /*CompoundTag potionEffect = new CompoundTag(); 251 potionEffect.putString("id", effect); 252 potionEffect.putInt("duration", duration); 253 customEffects.add(MobEffectInstance.load(potionEffect)); 254 *///?} 255 //? if >1.21.4 { 256 stack.set(DataComponents.POTION_CONTENTS, new PotionContents(Optional.empty(), Optional.of(color), customEffects, Optional.of(I18n.get("potion.infinity.skeleton")))); 257 //?} else if >1.21 { 258 /*stack.set(DataComponents.POTION_CONTENTS, new PotionContents(Optional.empty(), Optional.of(color), customEffects)); 259 stack.set(DataComponents.ITEM_NAME, Component.translatable("potion.infinity.skeleton")); 260 *///?} else { 261 /*PotionUtils.setCustomEffects(stack, customEffects); 262 stack.setHoverName(Component.translatable("potion.infinity.skeleton")); 263 *///?} 264 return stack; 265 } 266 267 @Override 268 public ItemStack getProjectile(ItemStack stack) { 269 return getProjectileType(); 270 } 271 272 public ItemStack getProjectileType() { 273 return setPotion(Items.TIPPED_ARROW.getDefaultInstance(), this.getColor(), this.getEffect(), this.getDuration()); 274 } 275 276 //? if >1.21 { 277 @Override 278 protected void dropCustomDeathLoot(ServerLevel world, DamageSource source, boolean causedByPlayer) { 279 super.dropCustomDeathLoot(world, source, causedByPlayer); 280 ItemStack weapon = source.getWeaponItem(); 281 Holder<Enchantment> looting = VersionMethods.getRegistry(world.getServer().registryAccess(), Registries.ENCHANTMENT). 282 //? if >1.21.4 { 283 getOrThrow 284 //?} else { 285 /*getHolderOrThrow 286 *///?} 287 (Enchantments.LOOTING); 288 int lootingLevel = weapon == null ? 0 : InfinityPlatform.INSTANCE.getEnchantments(weapon, world.getServer()).getLevel(looting); 289 dropEquipment(lootingLevel, world); 290 } 291 //?} else { 292 /*@Override 293 protected void dropCustomDeathLoot(DamageSource source, int lootingLevel, boolean allowDrops) { 294 super.dropCustomDeathLoot(source, lootingLevel, allowDrops); 295 dropEquipment(lootingLevel, (ServerLevel) this.level()); 296 } 297 *///?} 298 299 private void dropEquipment(int lootingLevel, ServerLevel world) { 300 int count = world.random.nextIntBetweenInclusive(0, 2 + lootingLevel); 301 this.spawnAtLocation( 302 //? if >1.21.4 303 world, 304 getProjectileType().copyWithCount(count)); 305 } 306}