@Override
 public void populate(Chunk chunk, Random random) {
   Vector3i min = chunk.getBlockMin();
   World world = (World) chunk.getWorld();
   BlockPos position = new BlockPos(min.getX(), min.getY(), min.getZ());
   ShrubType stype = ShrubTypes.TALL_GRASS;
   List<ShrubType> result;
   // The vanilla populator places down grass in batches of 128, which is a
   // decent enough amount in order to get nice 'patches' of grass so we
   // divide the total count into batches of 128.
   int n = (int) Math.ceil(this.count.getFlooredAmount(random) / 128f);
   for (int i = 0; i < n; i++) {
     BlockPos pos = position.add(random.nextInt(16) + 8, 0, random.nextInt(16) + 8);
     pos = world.getTopSolidOrLiquidBlock(pos).add(0, 1, 0);
     if (this.override != null) {
       Location<Chunk> pos2 = new Location<>(chunk, VecHelper.toVector(pos));
       stype = this.override.apply(pos2);
     } else {
       result = this.types.get(random);
       if (result.isEmpty()) {
         continue;
       }
       stype = result.get(0);
     }
     BlockTallGrass.EnumType type = (BlockTallGrass.EnumType) (Object) stype;
     this.tallGrassState =
         Blocks.tallgrass.getDefaultState().withProperty(BlockTallGrass.TYPE, type);
     generate(world, random, pos);
   }
 }
Example #2
0
 public static CompletableFuture<Boolean> doesChunkExist(
     WorldServer world, IChunkLoader chunkLoader, Vector3i chunkCoords) {
   int x = chunkCoords.getX();
   int z = chunkCoords.getZ();
   if (!(chunkLoader instanceof IMixinAnvilChunkLoader)
       || !SpongeChunkLayout.instance.isValidChunk(x, chunkCoords.getY(), z)) {
     return CompletableFuture.completedFuture(false);
   }
   return SpongeScheduler.getInstance()
       .submitAsyncTask(() -> ((IMixinAnvilChunkLoader) chunkLoader).chunkExists(world, x, z));
 }
Example #3
0
 @Subscribe
 public void onChunkPreGenerator(ChunkPreGenerateEvent event) {
   org.spongepowered.api.world.Chunk chunk = event.getChunk();
   World world = chunk.getWorld();
   final String worldname = world.getName();
   if (MainUtil.worldBorder.containsKey(worldname)) {
     final int border = MainUtil.getBorder(worldname);
     Vector3i min = world.getBlockMin();
     final int x = Math.abs(min.getX());
     final int z = Math.abs(min.getZ());
     if ((x > border) || (z > border)) {
       // TODO cancel this chunk from loading
       // - Currently not possible / this event doesn't seem to be called
     }
   }
 }
Example #4
0
  /**
   * Return the blocks that will be moved with this elevator
   *
   * @return The blocks that this lift will move
   */
  public LiftContents getContents() {
    Set<Vector3i> blocks = new HashSet<Vector3i>();
    Set<Vector3i> edgeBlocks = new HashSet<Vector3i>();
    Vector3i location = position.add(0, -1, 0);
    travelBlocks(location, location, blocks, new HashSet<Vector3i>(), edgeBlocks);

    return new LiftContents(this, edgeBlocks, blocks);
  }
Example #5
0
 public static CompletableFuture<Optional<DataContainer>> getChunkData(
     WorldServer world, IChunkLoader chunkLoader, Vector3i chunkCoords) {
   int x = chunkCoords.getX();
   int y = chunkCoords.getY();
   int z = chunkCoords.getZ();
   if (!(chunkLoader instanceof IMixinAnvilChunkLoader)
       || !SpongeChunkLayout.instance.isValidChunk(x, y, z)) {
     return CompletableFuture.completedFuture(Optional.empty());
   }
   File worldDir = ((IMixinAnvilChunkLoader) chunkLoader).getWorldDir().toFile();
   return SpongeScheduler.getInstance()
       .submitAsyncTask(
           () -> {
             DataInputStream stream = RegionFileCache.getChunkInputStream(worldDir, x, z);
             return Optional.ofNullable(readDataFromRegion(stream));
           });
 }
Example #6
0
  /**
   * Go through the blocks, checking for valid ones The way this works is:
   *
   * <ul>
   *   <li>Adds the current location to the list of valid locations
   *   <li>Checks if the current block is within {@link LiftPlatesConfig#maxLiftSize}
   *   <li>Makes sure the current block is of the same type and data as the central block
   *   <li>If large lifts are not enabled in the configuration, also checks that the block above is
   *       a pressureplate (If any of the previous conditions are not met, the method does not
   *       continue)
   *   <li>Adds the current location to the list of valid locations
   *   <li>Runs the method on {@link LiftUtil#NSEW_FACES}, excluding locations that have already
   *       been visited, with the same sets of valid and visited locations
   * </ul>
   *
   * @param start The origin block
   * @param current The current block
   * @param validLocations The list of already travelled and valid locations
   * @param visited The list of already travelled (not necessarily valid) locations
   */
  private void travelBlocks(
      Vector3i start,
      Vector3i current,
      Set<Vector3i> validLocations,
      Set<Vector3i> visited,
      Set<Vector3i> edgeBlocks) {
    visited.add(current);

    LiftPlatesConfig config = manager.getPlugin().getConfiguration();
    final int maxDist = config.maxLiftSize * config.maxLiftSize;
    if (start.distanceSquared(current) > maxDist) { // Too far away
      edgeBlocks.add(current);
      return;
    }

    final World world = manager.getWorld();
    if (!world.getBlock(start).equals(world.getBlock(current))) { // Different block type
      edgeBlocks.add(current);
      return;
    }

    if (!config.recursiveLifts
        && !LiftUtil.isPressurePlate(
            world.getBlockType(current.add(0, 1, 0)))) { // Not a pressure plate
      edgeBlocks.add(current);
      return;
    }

    validLocations.add(current);

    for (int i = 1; i < config.liftHeight; ++i) {
      validLocations.add(current.add(0, i, 0));
    }

    for (Direction face : LiftUtil.NSEW_FACES) {
      Vector3i newLoc = current.add(face.toVector3d().toInt());
      if (visited.contains(newLoc)) {
        continue;
      }

      travelBlocks(start, newLoc, validLocations, visited, edgeBlocks);
    }
  }
Example #7
0
 public BoundingBox2(Vector3i parA, Vector3i parB) {
   int ax, ay, bx, by;
   if (parA.getX() < parB.getX()) {
     ax = parA.getX();
     bx = parB.getX();
   } else {
     ax = parB.getX();
     bx = parA.getX();
   }
   if (parA.getZ() < parB.getZ()) {
     ay = parA.getZ();
     by = parB.getZ();
   } else {
     ay = parB.getZ();
     by = parA.getZ();
   }
   a = new Vector2i(ax, ay);
   b = new Vector2i(bx, by);
 }
Example #8
0
 @Override
 public Extent getExtentView(Vector3i newMin, Vector3i newMax) {
   checkBlockBounds(newMin.getX(), newMin.getY(), newMin.getZ());
   checkBlockBounds(newMax.getX(), newMax.getY(), newMax.getZ());
   return new ExtentViewDownsize(this, newMin, newMax);
 }
Example #9
0
 @Override
 public Optional<Chunk> loadChunk(Vector3i position, boolean shouldGenerate) {
   return loadChunk(position.getX(), position.getY(), position.getZ(), shouldGenerate);
 }
Example #10
0
@NonnullByDefault
@Mixin(net.minecraft.world.World.class)
public abstract class MixinWorld implements World, IMixinWorld {

  private static final Vector3i BLOCK_MIN = new Vector3i(-30000000, 0, -30000000);
  private static final Vector3i BLOCK_MAX = new Vector3i(30000000, 256, 30000000).sub(1, 1, 1);
  private static final Vector3i BLOCK_SIZE = BLOCK_MAX.sub(BLOCK_MIN).add(1, 1, 1);
  private static final Vector2i BIOME_MIN = BLOCK_MIN.toVector2(true);
  private static final Vector2i BIOME_MAX = BLOCK_MAX.toVector2(true);
  private static final Vector2i BIOME_SIZE = BIOME_MAX.sub(BIOME_MIN).add(1, 1);
  private static final String CHECK_NO_ENTITY_COLLISION =
      "checkNoEntityCollision(Lnet/minecraft/util/AxisAlignedBB;Lnet/minecraft/entity/Entity;)Z";
  private static final String GET_ENTITIES_WITHIN_AABB =
      "Lnet/minecraft/world/World;getEntitiesWithinAABBExcludingEntity(Lnet/minecraft/entity/Entity;Lnet/minecraft/util/AxisAlignedBB;)Ljava/util/List;";
  public SpongeBlockSnapshotBuilder builder = new SpongeBlockSnapshotBuilder();
  private boolean keepSpawnLoaded;
  private Context worldContext;
  private SpongeChunkProvider spongegen;
  protected boolean processingExplosion = false;
  private SpongeConfig<?> activeConfig;

  // @formatter:off
  @Shadow @Final public boolean isRemote;
  @Shadow @Final public WorldProvider provider;
  @Shadow @Final public Random rand;
  @Shadow @Final public List<net.minecraft.entity.Entity> loadedEntityList;
  @Shadow @Final public List<net.minecraft.tileentity.TileEntity> loadedTileEntityList;
  @Shadow @Final private net.minecraft.world.border.WorldBorder worldBorder;
  @Shadow @Final public List<EntityPlayer> playerEntities;
  @Shadow protected boolean scheduledUpdatesAreImmediate;
  @Shadow protected WorldInfo worldInfo;

  @Shadow
  public abstract net.minecraft.world.border.WorldBorder shadow$getWorldBorder();

  @Shadow
  public abstract EnumDifficulty shadow$getDifficulty();

  @Shadow
  public net.minecraft.world.World init() {
    // Should never be overwritten because this is @Shadow'ed
    throw new RuntimeException("Bad things have happened");
  }

  @Shadow
  public abstract void onEntityAdded(net.minecraft.entity.Entity entityIn);

  @Shadow
  public abstract void updateEntity(net.minecraft.entity.Entity ent);

  @Shadow
  public abstract net.minecraft.world.chunk.Chunk getChunkFromBlockCoords(BlockPos pos);

  @Shadow
  public abstract boolean isBlockLoaded(BlockPos pos);

  @Shadow
  public abstract boolean addWeatherEffect(net.minecraft.entity.Entity entityIn);

  @Shadow
  public abstract BiomeGenBase getBiomeGenForCoords(BlockPos pos);

  @Shadow
  public abstract IChunkProvider getChunkProvider();

  @Shadow
  public abstract WorldChunkManager getWorldChunkManager();

  @Shadow
  @Nullable
  public abstract net.minecraft.tileentity.TileEntity getTileEntity(BlockPos pos);

  @Shadow
  public abstract boolean isBlockPowered(BlockPos pos);

  @Shadow
  public abstract IBlockState getBlockState(BlockPos pos);

  @Shadow
  public abstract net.minecraft.world.chunk.Chunk getChunkFromChunkCoords(int chunkX, int chunkZ);

  @Shadow
  public abstract boolean isChunkLoaded(int x, int z, boolean allowEmpty);

  @Shadow
  public abstract net.minecraft.world.Explosion newExplosion(
      net.minecraft.entity.Entity entityIn,
      double x,
      double y,
      double z,
      float strength,
      boolean isFlaming,
      boolean isSmoking);

  @Shadow
  public abstract List<net.minecraft.entity.Entity> getEntities(
      Class<net.minecraft.entity.Entity> entityType,
      com.google.common.base.Predicate<net.minecraft.entity.Entity> filter);

  @Shadow
  public abstract List<net.minecraft.entity.Entity> getEntitiesWithinAABBExcludingEntity(
      net.minecraft.entity.Entity entityIn, AxisAlignedBB bb);

  // @formatter:on
  @Inject(method = "<init>", at = @At("RETURN"))
  public void onConstructed(
      ISaveHandler saveHandlerIn,
      WorldInfo info,
      WorldProvider providerIn,
      Profiler profilerIn,
      boolean client,
      CallbackInfo ci) {
    if (info == null) {
      SpongeImpl.getLogger()
          .warn(
              "World constructed without a WorldInfo! This will likely cause problems. Subsituting dummy info.",
              new RuntimeException("Stack trace:"));
      this.worldInfo =
          new WorldInfo(
              new WorldSettings(0, WorldSettings.GameType.NOT_SET, false, false, WorldType.DEFAULT),
              "sponge$dummy_world");
    }
    this.worldContext = new Context(Context.WORLD_KEY, this.worldInfo.getWorldName());
    if (SpongeImpl.getGame().getPlatform().getType() == Platform.Type.SERVER) {
      this.worldBorder.addListener(new PlayerBorderListener(providerIn.getDimensionId()));
    }
    this.activeConfig = SpongeHooks.getActiveConfig((net.minecraft.world.World) (Object) this);
  }

  @Override
  public SpongeBlockSnapshot createSpongeBlockSnapshot(
      IBlockState state, IBlockState extended, BlockPos pos, int updateFlag) {
    this.builder.reset();
    Location<World> location = new Location<>((World) this, VecHelper.toVector(pos));
    this.builder
        .blockState((BlockState) state)
        .extendedState((BlockState) extended)
        .worldId(location.getExtent().getUniqueId())
        .position(location.getBlockPosition());
    Optional<UUID> creator = getCreator(pos.getX(), pos.getY(), pos.getZ());
    Optional<UUID> notifier = getNotifier(pos.getX(), pos.getY(), pos.getZ());
    if (creator.isPresent()) {
      this.builder.creator(creator.get());
    }
    if (notifier.isPresent()) {
      this.builder.notifier(notifier.get());
    }
    if (state.getBlock() instanceof ITileEntityProvider) {
      net.minecraft.tileentity.TileEntity te = getTileEntity(pos);
      if (te != null) {
        TileEntity tile = (TileEntity) te;
        for (DataManipulator<?, ?> manipulator : tile.getContainers()) {
          this.builder.add(manipulator);
        }
        NBTTagCompound nbt = new NBTTagCompound();
        te.writeToNBT(nbt);
        this.builder.unsafeNbt(nbt);
      }
    }
    return new SpongeBlockSnapshot(this.builder, updateFlag);
  }

  @SuppressWarnings("rawtypes")
  @Inject(
      method =
          "getCollidingBoundingBoxes(Lnet/minecraft/entity/Entity;Lnet/minecraft/util/AxisAlignedBB;)Ljava/util/List;",
      at = @At("HEAD"),
      cancellable = true)
  public void onGetCollidingBoundingBoxes(
      net.minecraft.entity.Entity entity, AxisAlignedBB axis, CallbackInfoReturnable<List> cir) {
    if (!entity.worldObj.isRemote && SpongeHooks.checkBoundingBoxSize(entity, axis)) {
      // Removing misbehaved living entities
      cir.setReturnValue(new ArrayList());
    }
  }

  @Override
  public UUID getUniqueId() {
    return ((WorldProperties) this.worldInfo).getUniqueId();
  }

  @Override
  public String getName() {
    return this.worldInfo.getWorldName();
  }

  @Override
  public Optional<Chunk> getChunk(int x, int y, int z) {
    if (!SpongeChunkLayout.instance.isValidChunk(x, y, z)) {
      return Optional.empty();
    }
    WorldServer worldserver = (WorldServer) (Object) this;
    net.minecraft.world.chunk.Chunk chunk = null;
    if (worldserver.theChunkProviderServer.chunkExists(x, z)) {
      chunk = worldserver.theChunkProviderServer.provideChunk(x, z);
    }
    return Optional.ofNullable((Chunk) chunk);
  }

  @Override
  public Optional<Chunk> loadChunk(Vector3i position, boolean shouldGenerate) {
    return loadChunk(position.getX(), position.getY(), position.getZ(), shouldGenerate);
  }

  @Override
  public Optional<Chunk> loadChunk(int x, int y, int z, boolean shouldGenerate) {
    if (!SpongeChunkLayout.instance.isValidChunk(x, y, z)) {
      return Optional.empty();
    }
    WorldServer worldserver = (WorldServer) (Object) this;
    net.minecraft.world.chunk.Chunk chunk = null;
    if (worldserver.theChunkProviderServer.chunkExists(x, z) || shouldGenerate) {
      chunk = worldserver.theChunkProviderServer.loadChunk(x, z);
    }
    return Optional.ofNullable((Chunk) chunk);
  }

  @Override
  public BlockState getBlock(int x, int y, int z) {
    checkBlockBounds(x, y, z);
    return (BlockState) getBlockState(new BlockPos(x, y, z));
  }

  @Override
  public BlockType getBlockType(int x, int y, int z) {
    checkBlockBounds(x, y, z);
    // avoid intermediate object creation from using BlockState
    return (BlockType) getChunkFromChunkCoords(x >> 4, z >> 4).getBlock(x, y, z);
  }

  @Override
  public void setBlock(int x, int y, int z, BlockState block) {
    setBlock(x, y, z, block, true);
  }

  @Override
  public BiomeType getBiome(int x, int z) {
    checkBiomeBounds(x, z);
    return (BiomeType) this.getBiomeGenForCoords(new BlockPos(x, 0, z));
  }

  @Override
  public void setBiome(int x, int z, BiomeType biome) {
    checkBiomeBounds(x, z);
    ((Chunk) getChunkFromChunkCoords(x >> 4, z >> 4)).setBiome(x, z, biome);
  }

  @SuppressWarnings("unchecked")
  @Override
  public Collection<Entity> getEntities() {
    return Lists.newArrayList((Collection<Entity>) (Object) this.loadedEntityList);
  }

  @SuppressWarnings("unchecked")
  @Override
  public Collection<Entity> getEntities(Predicate<Entity> filter) {
    // This already returns a new copy
    return (Collection<Entity>)
        (Object)
            this.getEntities(
                net.minecraft.entity.Entity.class,
                Functional.java8ToGuava((Predicate<net.minecraft.entity.Entity>) (Object) filter));
  }

  @Override
  public Optional<Entity> createEntity(EntityType type, Vector3d position) {
    checkNotNull(type, "The entity type cannot be null!");
    checkNotNull(position, "The position cannot be null!");

    Entity entity = null;

    Class<? extends Entity> entityClass = type.getEntityClass();
    double x = position.getX();
    double y = position.getY();
    double z = position.getZ();

    if (entityClass.isAssignableFrom(EntityPlayerMP.class)
        || entityClass.isAssignableFrom(EntityDragonPart.class)) {
      // Unable to construct these
      return Optional.empty();
    }

    net.minecraft.world.World world = (net.minecraft.world.World) (Object) this;

    // Not all entities have a single World parameter as their constructor
    if (entityClass.isAssignableFrom(EntityLightningBolt.class)) {
      entity = (Entity) new EntityLightningBolt(world, x, y, z);
    } else if (entityClass.isAssignableFrom(EntityEnderPearl.class)) {
      EntityArmorStand tempEntity = new EntityArmorStand(world, x, y, z);
      tempEntity.posY -= tempEntity.getEyeHeight();
      entity = (Entity) new EntityEnderPearl(world, tempEntity);
      ((EnderPearl) entity).setShooter(ProjectileSource.UNKNOWN);
    }

    // Some entities need to have non-null fields (and the easiest way to
    // set them is to use the more specialised constructor).
    if (entityClass.isAssignableFrom(EntityFallingBlock.class)) {
      entity = (Entity) new EntityFallingBlock(world, x, y, z, Blocks.sand.getDefaultState());
    } else if (entityClass.isAssignableFrom(EntityItem.class)) {
      entity = (Entity) new EntityItem(world, x, y, z, new ItemStack(Blocks.stone));
    }

    if (entity == null) {
      try {
        entity = ConstructorUtils.invokeConstructor(entityClass, this);
        ((net.minecraft.entity.Entity) entity).setPosition(x, y, z);
      } catch (Exception e) {
        SpongeImpl.getLogger().error(ExceptionUtils.getStackTrace(e));
      }
    }

    // TODO - replace this with an actual check
    /*
    if (entity instanceof EntityHanging) {
        if (((EntityHanging) entity).facingDirection == null) {
            // TODO Some sort of detection of a valid direction?
            // i.e scan immediate blocks for something to attach onto.
            ((EntityHanging) entity).facingDirection = EnumFacing.NORTH;
        }
        if (!((EntityHanging) entity).onValidSurface()) {
            return Optional.empty();
        }
    }*/

    // Last chance to fix null fields
    if (entity instanceof EntityPotion) {
      // make sure EntityPotion.potionDamage is not null
      ((EntityPotion) entity).getPotionDamage();
    } else if (entity instanceof EntityPainting) {
      // This is default when art is null when reading from NBT, could
      // choose a random art instead?
      ((EntityPainting) entity).art = EnumArt.KEBAB;
    }

    return Optional.ofNullable(entity);
  }

  @Override
  public Optional<Entity> createEntity(DataContainer entityContainer) {
    // TODO once entity containers are implemented
    return Optional.empty();
  }

  @Override
  public Optional<Entity> createEntity(DataContainer entityContainer, Vector3d position) {
    // TODO once entity containers are implemented
    return Optional.empty();
  }

  @Override
  public Optional<Entity> restoreSnapshot(EntitySnapshot snapshot, Vector3d position) {
    EntitySnapshot entitySnapshot = snapshot.withLocation(new Location<>(this, position));
    return entitySnapshot.restore();
  }

  @Override
  public WorldBorder getWorldBorder() {
    return (WorldBorder) shadow$getWorldBorder();
  }

  @Override
  public WorldBorder.ChunkPreGenerate newChunkPreGenerate(Vector3d center, double diameter) {
    return new SpongeChunkPreGenerate(this, center, diameter);
  }

  @Override
  public Dimension getDimension() {
    return (Dimension) this.provider;
  }

  @Override
  public boolean doesKeepSpawnLoaded() {
    return this.keepSpawnLoaded;
  }

  @Override
  public void setKeepSpawnLoaded(boolean keepLoaded) {
    this.keepSpawnLoaded = keepLoaded;
  }

  @Override
  public SpongeConfig<SpongeConfig.WorldConfig> getWorldConfig() {
    return ((IMixinWorldInfo) this.worldInfo).getWorldConfig();
  }

  @Override
  public Optional<Entity> getEntity(UUID uuid) {
    // Note that MixinWorldServer is properly overriding this to use it's own mapping.
    for (net.minecraft.entity.Entity entity : this.loadedEntityList) {
      if (entity.getUniqueID().equals(uuid)) {
        return Optional.of((Entity) entity);
      }
    }
    return Optional.empty();
  }

  @SuppressWarnings("unchecked")
  @Override
  public Iterable<Chunk> getLoadedChunks() {
    return (List<Chunk>) (List<?>) ((ChunkProviderServer) this.getChunkProvider()).loadedChunks;
  }

  @Override
  public boolean unloadChunk(Chunk chunk) {
    checkArgument(chunk != null, "Chunk cannot be null!");
    return chunk.unloadChunk();
  }

  @Override
  public WorldCreationSettings getCreationSettings() {
    WorldProperties properties = this.getProperties();

    // Create based on WorldProperties
    WorldSettings settings = new WorldSettings(this.worldInfo);
    IMixinWorldSettings mixin = (IMixinWorldSettings) (Object) settings;
    mixin.setDimensionType(properties.getDimensionType());
    mixin.setGeneratorSettings(properties.getGeneratorSettings());
    mixin.setGeneratorModifiers(properties.getGeneratorModifiers());
    mixin.setEnabled(true);
    mixin.setKeepSpawnLoaded(this.keepSpawnLoaded);
    mixin.setLoadOnStartup(properties.loadOnStartup());

    return (WorldCreationSettings) (Object) settings;
  }

  @Override
  public void updateWorldGenerator() {

    IMixinWorldType worldType = (IMixinWorldType) this.getProperties().getGeneratorType();
    // Get the default generator for the world type
    DataContainer generatorSettings = this.getProperties().getGeneratorSettings();

    SpongeWorldGenerator newGenerator = worldType.createGenerator(this, generatorSettings);
    // If the base generator is an IChunkProvider which implements
    // IPopulatorProvider we request that it add its populators not covered
    // by the base generation populator
    if (newGenerator.getBaseGenerationPopulator() instanceof IChunkProvider) {
      // We check here to ensure that the IPopulatorProvider is one of our mixed in ones and not
      // from a mod chunk provider extending a provider that we mixed into
      if (WorldGenConstants.isValid(
          (IChunkProvider) newGenerator.getBaseGenerationPopulator(), IPopulatorProvider.class)) {
        ((IPopulatorProvider) newGenerator.getBaseGenerationPopulator())
            .addPopulators(newGenerator);
      }
    } else if (newGenerator.getBaseGenerationPopulator() instanceof IPopulatorProvider) {
      // If its not a chunk provider but is a populator provider then we call it as well
      ((IPopulatorProvider) newGenerator.getBaseGenerationPopulator()).addPopulators(newGenerator);
    }

    // Re-apply all world generator modifiers
    WorldCreationSettings creationSettings = this.getCreationSettings();

    for (WorldGeneratorModifier modifier : this.getProperties().getGeneratorModifiers()) {
      modifier.modifyWorldGenerator(creationSettings, generatorSettings, newGenerator);
    }

    this.spongegen = createChunkProvider(newGenerator);
    this.spongegen.setGenerationPopulators(newGenerator.getGenerationPopulators());
    this.spongegen.setPopulators(newGenerator.getPopulators());
    this.spongegen.setBiomeOverrides(newGenerator.getBiomeSettings());

    ChunkProviderServer chunkProviderServer = (ChunkProviderServer) this.getChunkProvider();
    chunkProviderServer.serverChunkGenerator = this.spongegen;
  }

  @Override
  public SpongeChunkProvider createChunkProvider(SpongeWorldGenerator newGenerator) {
    return new SpongeChunkProvider(
        (net.minecraft.world.World) (Object) this,
        newGenerator.getBaseGenerationPopulator(),
        newGenerator.getBiomeGenerator());
  }

  @Override
  public void onSpongeEntityAdded(net.minecraft.entity.Entity entity) {
    this.onEntityAdded(entity);
  }

  @Override
  public WorldGenerator getWorldGenerator() {
    return this.spongegen;
  }

  @Override
  public WorldProperties getProperties() {
    return (WorldProperties) this.worldInfo;
  }

  @Override
  public Location<World> getSpawnLocation() {
    return new Location<>(
        this, this.worldInfo.getSpawnX(), this.worldInfo.getSpawnY(), this.worldInfo.getSpawnZ());
  }

  @Override
  public Context getContext() {
    return this.worldContext;
  }

  @Override
  public Optional<TileEntity> getTileEntity(int x, int y, int z) {
    net.minecraft.tileentity.TileEntity tileEntity = getTileEntity(new BlockPos(x, y, z));
    if (tileEntity == null) {
      return Optional.empty();
    } else {
      return Optional.of((TileEntity) tileEntity);
    }
  }

  @Override
  public Vector2i getBiomeMin() {
    return BIOME_MIN;
  }

  @Override
  public Vector2i getBiomeMax() {
    return BIOME_MAX;
  }

  @Override
  public Vector2i getBiomeSize() {
    return BIOME_SIZE;
  }

  @Override
  public Vector3i getBlockMin() {
    return BLOCK_MIN;
  }

  @Override
  public Vector3i getBlockMax() {
    return BLOCK_MAX;
  }

  @Override
  public Vector3i getBlockSize() {
    return BLOCK_SIZE;
  }

  @Override
  public boolean containsBiome(int x, int z) {
    return VecHelper.inBounds(x, z, BIOME_MIN, BIOME_MAX);
  }

  @Override
  public boolean containsBlock(int x, int y, int z) {
    return VecHelper.inBounds(x, y, z, BLOCK_MIN, BLOCK_MAX);
  }

  private void checkBiomeBounds(int x, int z) {
    if (!containsBiome(x, z)) {
      throw new PositionOutOfBoundsException(new Vector2i(x, z), BIOME_MIN, BIOME_MAX);
    }
  }

  private void checkBlockBounds(int x, int y, int z) {
    if (!containsBlock(x, y, z)) {
      throw new PositionOutOfBoundsException(new Vector3i(x, y, z), BLOCK_MIN, BLOCK_MAX);
    }
  }

  @Override
  public Difficulty getDifficulty() {
    return (Difficulty) (Object) this.shadow$getDifficulty();
  }

  @SuppressWarnings({"unchecked", "rawtypes"})
  private List<Player> getPlayers() {
    return (List)
        ((net.minecraft.world.World) (Object) this)
            .getPlayers(EntityPlayerMP.class, Predicates.alwaysTrue());
  }

  @Override
  public void sendMessage(ChatType type, Text message) {
    checkNotNull(type, "type");
    checkNotNull(message, "message");

    for (Player player : this.getPlayers()) {
      player.sendMessage(type, message);
    }
  }

  @Override
  public void sendTitle(Title title) {
    checkNotNull(title, "title");

    for (Player player : getPlayers()) {
      player.sendTitle(title);
    }
  }

  @Override
  public void resetTitle() {
    getPlayers().forEach(Player::resetTitle);
  }

  @Override
  public void clearTitle() {
    getPlayers().forEach(Player::clearTitle);
  }

  @SuppressWarnings("unchecked")
  @Override
  public Collection<TileEntity> getTileEntities() {
    return Lists.newArrayList((List<TileEntity>) (Object) this.loadedTileEntityList);
  }

  @SuppressWarnings("unchecked")
  @Override
  public Collection<TileEntity> getTileEntities(Predicate<TileEntity> filter) {
    return ((List<TileEntity>) (Object) this.loadedTileEntityList)
        .stream()
        .filter(filter)
        .collect(Collectors.toList());
  }

  @Override
  public boolean isLoaded() {
    return DimensionManager.getWorldFromDimId(this.provider.getDimensionId()) != null;
  }

  @Override
  public Optional<String> getGameRule(String gameRule) {
    return this.getProperties().getGameRule(gameRule);
  }

  @Override
  public Map<String, String> getGameRules() {
    return this.getProperties().getGameRules();
  }

  @Override
  public void triggerExplosion(Explosion explosion) {
    checkNotNull(explosion, "explosion");
    checkNotNull(explosion.getOrigin(), "origin");

    newExplosion(
        (net.minecraft.entity.Entity) explosion.getSourceExplosive().orElse(null),
        explosion.getOrigin().getX(),
        explosion.getOrigin().getY(),
        explosion.getOrigin().getZ(),
        explosion.getRadius(),
        explosion.canCauseFire(),
        explosion.shouldBreakBlocks());
  }

  @Override
  public Extent getExtentView(Vector3i newMin, Vector3i newMax) {
    checkBlockBounds(newMin.getX(), newMin.getY(), newMin.getZ());
    checkBlockBounds(newMax.getX(), newMax.getY(), newMax.getZ());
    return new ExtentViewDownsize(this, newMin, newMax);
  }

  @Override
  public Extent getExtentView(DiscreteTransform3 transform) {
    return new ExtentViewTransform(this, transform);
  }

  @Override
  public MutableBiomeAreaWorker<? extends World> getBiomeWorker() {
    return new SpongeMutableBiomeAreaWorker<>(this);
  }

  @Override
  public MutableBlockVolumeWorker<? extends World> getBlockWorker() {
    return new SpongeMutableBlockVolumeWorker<>(this);
  }

  @Override
  public BlockSnapshot createSnapshot(int x, int y, int z) {
    World world = this;
    BlockState state = world.getBlock(x, y, z);
    Optional<TileEntity> te = world.getTileEntity(x, y, z);
    SpongeBlockSnapshotBuilder builder =
        new SpongeBlockSnapshotBuilder()
            .blockState(state)
            .worldId(world.getUniqueId())
            .position(new Vector3i(x, y, z));
    Optional<UUID> creator = getCreator(x, y, z);
    Optional<UUID> notifier = getNotifier(x, y, z);
    if (creator.isPresent()) {
      builder.creator(creator.get());
    }
    if (notifier.isPresent()) {
      builder.notifier(notifier.get());
    }
    if (te.isPresent()) {
      final TileEntity tileEntity = te.get();
      for (DataManipulator<?, ?> manipulator : tileEntity.getContainers()) {
        builder.add(manipulator);
      }
      final NBTTagCompound compound = new NBTTagCompound();
      ((net.minecraft.tileentity.TileEntity) tileEntity).writeToNBT(compound);
      builder.unsafeNbt(compound);
    }
    return builder.build();
  }

  @Override
  public boolean restoreSnapshot(BlockSnapshot snapshot, boolean force, boolean notifyNeighbors) {
    return snapshot.restore(force, notifyNeighbors);
  }

  @Override
  public boolean restoreSnapshot(
      int x, int y, int z, BlockSnapshot snapshot, boolean force, boolean notifyNeighbors) {
    snapshot = snapshot.withLocation(new Location<>(this, new Vector3i(x, y, z)));
    return snapshot.restore(force, notifyNeighbors);
  }

  @Override
  public Optional<UUID> getCreator(int x, int y, int z) {
    BlockPos pos = new BlockPos(x, y, z);
    IMixinChunk spongeChunk = (IMixinChunk) getChunkFromBlockCoords(pos);
    Optional<User> user = spongeChunk.getBlockOwner(pos);
    if (user.isPresent()) {
      return Optional.of(user.get().getUniqueId());
    } else {
      return Optional.empty();
    }
  }

  @Override
  public Optional<UUID> getNotifier(int x, int y, int z) {
    BlockPos pos = new BlockPos(x, y, z);
    IMixinChunk spongeChunk = (IMixinChunk) getChunkFromBlockCoords(pos);
    Optional<User> user = spongeChunk.getBlockNotifier(pos);
    if (user.isPresent()) {
      return Optional.of(user.get().getUniqueId());
    } else {
      return Optional.empty();
    }
  }

  @Override
  public void setCreator(int x, int y, int z, @Nullable UUID uuid) {
    BlockPos pos = new BlockPos(x, y, z);
    IMixinChunk spongeChunk = (IMixinChunk) getChunkFromBlockCoords(pos);
    spongeChunk.setBlockCreator(pos, uuid);
  }

  @Override
  public void setNotifier(int x, int y, int z, @Nullable UUID uuid) {
    BlockPos pos = new BlockPos(x, y, z);
    IMixinChunk spongeChunk = (IMixinChunk) getChunkFromBlockCoords(pos);
    spongeChunk.setBlockNotifier(pos, uuid);
  }

  @Nullable
  @Override
  public EntityPlayer getClosestPlayerToEntityWhoAffectsSpawning(
      net.minecraft.entity.Entity entity, double distance) {
    return this.getClosestPlayerWhoAffectsSpawning(entity.posX, entity.posY, entity.posZ, distance);
  }

  @Nullable
  @Override
  public EntityPlayer getClosestPlayerWhoAffectsSpawning(
      double x, double y, double z, double distance) {
    double bestDistance = -1.0D;
    EntityPlayer result = null;

    for (Object entity : this.playerEntities) {
      EntityPlayer player = (EntityPlayer) entity;
      if (player == null || player.isDead || !((IMixinEntityPlayer) player).affectsSpawning()) {
        continue;
      }

      double playerDistance = player.getDistanceSq(x, y, z);

      if ((distance < 0.0D || playerDistance < distance * distance)
          && (bestDistance == -1.0D || playerDistance < bestDistance)) {
        bestDistance = playerDistance;
        result = player;
      }
    }

    return result;
  }

  @Redirect(
      method = "isAnyPlayerWithinRangeAt",
      at =
          @At(
              value = "INVOKE",
              target = "Lcom/google/common/base/Predicate;apply(Ljava/lang/Object;)Z",
              remap = false))
  public boolean onIsAnyPlayerWithinRangePredicate(
      com.google.common.base.Predicate<EntityPlayer> predicate, Object object) {
    EntityPlayer player = (EntityPlayer) object;
    return !(player.isDead || !((IMixinEntityPlayer) player).affectsSpawning())
        && predicate.apply(player);
  }

  // For invisibility
  @Redirect(
      method = CHECK_NO_ENTITY_COLLISION,
      at = @At(value = "INVOKE", target = GET_ENTITIES_WITHIN_AABB))
  public List<net.minecraft.entity.Entity> filterInvisibile(
      net.minecraft.world.World world,
      net.minecraft.entity.Entity entityIn,
      AxisAlignedBB axisAlignedBB) {
    List<net.minecraft.entity.Entity> entities =
        world.getEntitiesWithinAABBExcludingEntity(entityIn, axisAlignedBB);
    Iterator<net.minecraft.entity.Entity> iterator = entities.iterator();
    while (iterator.hasNext()) {
      net.minecraft.entity.Entity entity = iterator.next();
      if (((IMixinEntity) entity).isVanished() && ((IMixinEntity) entity).ignoresCollision()) {
        iterator.remove();
      }
    }
    return entities;
  }

  @Redirect(
      method = "getClosestPlayer",
      at =
          @At(
              value = "INVOKE",
              target = "Lcom/google/common/base/Predicate;apply(Ljava/lang/Object;)Z",
              remap = false))
  private boolean onGetClosestPlayerCheck(
      com.google.common.base.Predicate<net.minecraft.entity.Entity> predicate,
      Object entityPlayer) {
    EntityPlayer player = (EntityPlayer) entityPlayer;
    IMixinEntity mixinEntity = (IMixinEntity) player;
    return predicate.apply(player) && !mixinEntity.isVanished();
  }

  /**
   * @author gabizou - February 7th, 2016
   *     <p>This will short circuit all other patches such that we control the entities being loaded
   *     by chunkloading and can throw our bulk entity event. This will bypass Forge's hook for
   *     individual entity events, but the SpongeModEventManager will still successfully throw the
   *     appropriate event and cancel the entities otherwise contained.
   * @param entities The entities being loaded
   * @param callbackInfo The callback info
   */
  @Final
  @Inject(method = "loadEntities", at = @At("HEAD"), cancellable = true)
  private void spongeLoadEntities(
      Collection<net.minecraft.entity.Entity> entities, CallbackInfo callbackInfo) {
    if (entities.isEmpty()) {
      // just return, no entities to load!
      callbackInfo.cancel();
      return;
    }
    List<Entity> entityList = new ArrayList<>();
    ImmutableList.Builder<EntitySnapshot> snapshotBuilder = ImmutableList.builder();
    for (net.minecraft.entity.Entity entity : entities) {
      entityList.add((Entity) entity);
      snapshotBuilder.add(((Entity) entity).createSnapshot());
    }
    SpawnCause cause = SpawnCause.builder().type(InternalSpawnTypes.CHUNK_LOAD).build();
    List<NamedCause> causes = new ArrayList<>();
    causes.add(NamedCause.source(cause));
    causes.add(NamedCause.of("World", this));
    SpawnEntityEvent.ChunkLoad chunkLoad =
        SpongeEventFactory.createSpawnEntityEventChunkLoad(
            Cause.of(causes), entityList, snapshotBuilder.build(), this);
    SpongeImpl.postEvent(chunkLoad);
    if (!chunkLoad.isCancelled()) {
      for (Entity successful : chunkLoad.getEntities()) {
        this.loadedEntityList.add((net.minecraft.entity.Entity) successful);
        this.onEntityAdded((net.minecraft.entity.Entity) successful);
      }
    }
    callbackInfo.cancel();
  }

  @Inject(method = "playSoundAtEntity", at = @At("HEAD"), cancellable = true)
  private void spongePlaySoundAtEntity(
      net.minecraft.entity.Entity entity,
      String name,
      float volume,
      float pitch,
      CallbackInfo callbackInfo) {
    if (((IMixinEntity) entity).isVanished()) {
      callbackInfo.cancel();
    }
  }

  @Override
  public void sendBlockChange(int x, int y, int z, BlockState state) {
    checkNotNull(state, "state");
    S23PacketBlockChange packet = new S23PacketBlockChange();
    packet.blockPosition = new BlockPos(x, y, z);
    packet.blockState = (IBlockState) state;

    for (EntityPlayer player : this.playerEntities) {
      if (player instanceof EntityPlayerMP) {
        ((EntityPlayerMP) player).playerNetServerHandler.sendPacket(packet);
      }
    }
  }

  @Override
  public void resetBlockChange(int x, int y, int z) {
    S23PacketBlockChange packet =
        new S23PacketBlockChange((net.minecraft.world.World) (Object) this, new BlockPos(x, y, z));

    for (EntityPlayer player : this.playerEntities) {
      if (player instanceof EntityPlayerMP) {
        ((EntityPlayerMP) player).playerNetServerHandler.sendPacket(packet);
      }
    }
  }

  /**
   * @author amaranth - April 25th, 2016
   * @reason Avoid 25 chunk map lookups per entity per tick by using neighbor pointers
   * @param xStart X block start coordinate
   * @param yStart Y block start coordinate
   * @param zStart Z block start coordinate
   * @param xEnd X block end coordinate
   * @param yEnd Y block end coordinate
   * @param zEnd Z block end coordinate
   * @param allowEmpty Whether empty chunks should be accepted
   * @return If the chunks for the area are loaded
   */
  @Overwrite
  public boolean isAreaLoaded(
      int xStart, int yStart, int zStart, int xEnd, int yEnd, int zEnd, boolean allowEmpty) {
    if (yEnd < 0 || yStart > 255) {
      return false;
    }

    xStart = xStart >> 4;
    zStart = zStart >> 4;
    xEnd = xEnd >> 4;
    zEnd = zEnd >> 4;

    Chunk base =
        (Chunk)
            ((IMixinChunkProviderServer) this.getChunkProvider()).getChunkIfLoaded(xStart, zStart);
    if (base == null) {
      return false;
    }

    for (int i = xStart; i <= xEnd; i++) {
      Optional<Chunk> column = base.getNeighbor(Direction.EAST);
      if (!column.isPresent()) {
        return false;
      }

      Chunk unwrapped = column.get();
      for (int j = zStart; j <= zEnd; j++) {
        Optional<Chunk> row = unwrapped.getNeighbor(Direction.SOUTH);
        if (!row.isPresent()) {
          return false;
        }

        if (!allowEmpty && ((net.minecraft.world.chunk.Chunk) row.get()).isEmpty()) {
          return false;
        }
      }
    }

    return true;
  }

  @Override
  public boolean isProcessingExplosion() {
    return this.processingExplosion;
  }

  @Override
  public SpongeConfig<?> getActiveConfig() {
    return this.activeConfig;
  }

  @Override
  public void setActiveConfig(SpongeConfig<?> config) {
    this.activeConfig = config;
  }
}
Example #11
0
 /**
  * Get the chunk at the given chunk coordinate position if it exists or if {@code shouldGenerate}
  * is true and the chunk is generated.
  *
  * @param chunkPosition The position
  * @param shouldGenerate True to generate a new chunk
  * @return The loaded or generated chunk, if already generated
  */
 default Optional<Chunk> loadChunk(Vector3i chunkPosition, boolean shouldGenerate) {
   return this.loadChunk(
       chunkPosition.getX(), chunkPosition.getY(), chunkPosition.getZ(), shouldGenerate);
 }
Example #12
0
 /**
  * Get the loaded chunk at the given chunk coordinate position.
  *
  * @param chunkPosition The position
  * @return The chunk, if available
  */
 default Optional<Chunk> getChunk(Vector3i chunkPosition) {
   return getChunk(chunkPosition.getX(), chunkPosition.getY(), chunkPosition.getZ());
 }
Example #13
0
 /**
  * Get the loaded chunk at the given block coordinate position.
  *
  * @param blockPosition The position
  * @return The chunk, if available
  */
 default Optional<Chunk> getChunkAtBlock(Vector3i blockPosition) {
   return getChunkAtBlock(blockPosition.getX(), blockPosition.getY(), blockPosition.getZ());
 }