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