public void strikePlayers(List<Player> toStrike) { for (Player player : toStrike) { Point playerPos = player.getScene().getPosition(); final int posX = GenericMath.floor(playerPos.getX()); final int posY = GenericMath.floor(playerPos.getY()); final int posZ = GenericMath.floor(playerPos.getZ()); for (int tries = 0; tries < 10; tries++) { // pick a random chunk between -4, -4, to 4, 4 relative to the player's position to strike // at int cx = (ra.nextBoolean() ? -1 : 1) * ra.nextInt(5); int cz = (ra.nextBoolean() ? -1 : 1) * ra.nextInt(5); // pick random coords to try to strike at inside the chunk (0, 0) to (15, 15) int rx = ra.nextInt(16); int rz = ra.nextInt(16); // pick a offset from the player's y position to strike at (-15 - +15) of their position int offsetY = (ra.nextBoolean() ? -1 : 1) * ra.nextInt(15); int x = posX + cx * 16 + rx; int y = posY + offsetY; int z = posZ + cz * 16 + rz; if (weather.isRainingAt(x, y, z, false)) { int lightning = 1; // 30% chance of extra lightning at the spot if (ra.nextInt(10) < 3) { lightning += ra.nextInt(MAX_LIGHTNING_BRANCHES); } for (int strikes = 0; strikes < lightning; strikes++) { float adjustX = 0.5F; float adjustY = 0.0F; float adjustZ = 0.5F; // if there are extra strikes, tweak their placement slightly if (strikes > 0) { adjustX += (ra.nextBoolean() ? -1 : 1) * ra.nextInt(2); adjustY += (ra.nextBoolean() ? -1 : 1) * ra.nextInt(8); adjustZ += (ra.nextBoolean() ? -1 : 1) * ra.nextInt(2); } World world = getWorld(); Point point = new Point(world, x + adjustX, y + adjustY, z + adjustZ); world.createAndSpawnEntity(point, Lightning.class, LoadOption.NO_LOAD); for (Player p : GeneralEffects.LIGHTNING_THUNDER.getNearbyPlayers(point, null, 600)) { double dist = p.getScene().getPosition().distanceSquared(point); float volume = (float) (10000F - Math.pow(dist, 0.73)); if (volume > 0) { GeneralEffects.LIGHTNING_THUNDER.adjust(volume, 0.7F).play(p, point); } } } // success, go to the next player break; } } } }
@Override public void onDynamicUpdate(Block block, long updateTime, int data) { final Random rand = GenericMath.getRandom(); if (rand.nextInt(25) == 0) { // can we spread? int max = MAX_PER_GROUP; for (IntVector3 coord : MUSHROOM_RANGE) { if (block.translate(coord).isMaterial(this) && --max <= 0) { return; } } Cause<?> cause = toCause(block); // spread from the source (4 times) Block newShroom; for (int i = 0; i < 4; i++) { newShroom = block.translate( rand.nextInt(3) - 1, rand.nextInt(2) - rand.nextInt(2), rand.nextInt(3) - 1); if (newShroom.isMaterial(VanillaMaterials.AIR) && this.canCreate(newShroom, (short) 0, cause)) { block = newShroom; } } // try to place at last if (block.isMaterial(VanillaMaterials.AIR) && this.canCreate(block, (short) 0, cause)) { this.onCreate(block, (short) 0, cause); } } // TODO : delay before update block.dynamicUpdate(updateTime + getGrowthTime(block), true); }
public SSAOPostProcessEffect() { kernel = new Vector3[kernelSize]; Random rng = new Random(); for (int i = 0; i < kernelSize; i++) { // Create a set of random vectors along the surface of a hemisphere. kernel[i] = new Vector3((rng.nextFloat() * 2) - 1, (rng.nextFloat() * 2) - 1, rng.nextFloat()); // Normalize the vector kernel[i] = kernel[i].normalize(); // Scale it into the hemisphere so the vectors aren't all along the surface. // We want the distance from the origin to fall off as we generate more points. float scale = (float) i / (float) kernelSize; scale = GenericMath.lerp(0.1f, 1.0f, scale * scale); kernel[i] = kernel[i].multiply(scale); } // Generate the noise texture. int[] texture = new int[noiseSize * noiseSize]; for (int i = 0; i < noiseSize * noiseSize; i++) { Color c = new Color(rng.nextFloat(), rng.nextFloat(), 0); texture[i] = c.getRGB(); } Vector2 resolution = ((Client) Spout.getEngine()).getResolution(); noiseScale = new Vector2(resolution.getX() / noiseSize, resolution.getY() / noiseSize); noise = new ClientTexture(texture, noiseSize, noiseSize); }
@Override public void onDynamicUpdate(Block block, long updateTime, int data) { if (block.translate(BlockFace.TOP).getLight() < this.getMinimumLightToGrow()) { block.dynamicUpdate(updateTime + getGrowthTime(block), true); return; } int chance = VanillaBlockMaterial.getCropGrowthChance(block) + 1; final Random rand = GenericMath.getRandom(); if (rand.nextInt(chance) == 0) { if (isFullyGrown(block)) { for (int i = 0; i < BlockFaces.NESW.size(); i++) { Block spread = block.translate(BlockFaces.NESW.get(i)); BlockMaterial material = spread.getMaterial(); if (material == VanillaMaterials.AIR) { BlockMaterial belowSpread = spread.translate(BlockFace.BOTTOM).getMaterial(); if (belowSpread.isMaterial( VanillaMaterials.FARMLAND, VanillaMaterials.DIRT, VanillaMaterials.GRASS)) { spread.setMaterial(this.getLastStageMaterial()); break; } } else if (material == getLastStageMaterial()) { break; } } } else { block.addData(1); } } block.dynamicUpdate(updateTime + getGrowthTime(block), true); }
@Override public void onTick(float dt) { final Random random = GenericMath.getRandom(); float secondsUntilWeatherChange = sky.getData().get(VanillaData.WEATHER_CHANGE_TIME); secondsUntilWeatherChange -= dt; if (forceWeatherUpdate.compareAndSet(true, false) || secondsUntilWeatherChange <= 0) { this.sky.updateWeather(getCurrent(), getForecast()); sky.getData().put(VanillaData.WORLD_WEATHER, getForecast()); final Weather current = getCurrent(); Weather forecast = current; while (forecast == current) { // When Rain/Snow or Thunderstorms occur, always go to Clear after. if (current == Weather.RAIN || current == Weather.THUNDERSTORM) { forecast = Weather.CLEAR; } else { forecast = Weather.get(random.nextInt(3)); } setForecast(forecast); } setForecast(forecast); secondsUntilWeatherChange = current.getBaseWeatherTime() + random.nextInt(current.getRandomWeatherTime()); if (Spout.debugMode()) { Spout.getLogger() .info( "Weather changed to: " + current + ", next change in " + secondsUntilWeatherChange / 1000F + "s"); } } float currentRainStrength = sky.getData().get(VanillaData.CURRENT_RAIN_STRENGTH); sky.getData().put(VanillaData.PREVIOUS_RAIN_STRENGTH, currentRainStrength); if (this.isRaining()) { currentRainStrength = Math.min(1.0f, currentRainStrength + 0.01f); } else { currentRainStrength = Math.max(0.0f, currentRainStrength - 0.01f); } sky.getData().put(VanillaData.CURRENT_RAIN_STRENGTH, currentRainStrength); if (hasLightning()) { lightning.onTick(dt); } if (getCurrent().isRaining()) { snowfall.onTick(dt); } sky.getData().put(VanillaData.WEATHER_CHANGE_TIME, secondsUntilWeatherChange); }
private long getGrowthTime(Block block) { return 120000L + GenericMath.getRandom().nextInt(120000); }
@Override public void onInteractBy(Entity entity, Block block, Action type, BlockFace clickedFace) { super.onInteractBy(entity, block, type, clickedFace); Slot inv = PlayerUtil.getHeldSlot(entity); if (inv != null && inv.get() != null && inv.get().isMaterial(Dye.BONE_MEAL) && type.equals(Action.RIGHT_CLICK)) { // This flag is used to determine if we should remove a Bone Meal if at least one block // gets a Tall Grass attached to the top of it, then we should remove a bone meal. boolean shouldConsume = false; final Random random = GenericMath.getRandom(); // Minecraft does grass growing by Bone Meal as follows. Keep in mind the radius is 8. // - Tall Grass is placed 9/10 times. // - If Tall Grass fails, place Dandelion 2/3 times (within the 1/10 window Tall Grass failed // on) // - If Dandelion fails, place Rose within the 1/3 times window that Dandelion failed (which // is within the 1/10 window Tall Grass failed on). for (int dx = -4; dx < 4; dx++) { for (int dy = -1; dy <= 1; dy++) { for (int dz = -4; dz < 4; dz++) { // Fertilization only occurs 1/3 times. if (random.nextInt(3) != 2) { continue; } // Grass/flowers have lower chance to go to a lower/higher height than the center block // is at. // It incurs another 1/3 times. Only do this when iterating over -1 or 1 on the dy, // otherwise its on the same // plane and we don't care. if (dy != 0) { if (random.nextInt(3) != 2) { continue; } } final Block around = block.translate(dx, dy, dz); // Only spread to Grass blocks if (!around.getMaterial().equals(VanillaMaterials.GRASS)) { continue; } final Block aboveAround = around.translate(BlockFace.TOP); // Make sure the block above the translated one is Air. if (!aboveAround.getMaterial().equals(VanillaMaterials.AIR)) { continue; } if (random.nextInt(10) != 0) { if (VanillaMaterials.TALL_GRASS.canAttachTo(around, BlockFace.TOP)) { aboveAround.setMaterial(VanillaMaterials.TALL_GRASS); shouldConsume = true; } } else if (random.nextInt(3) != 0) { if (VanillaMaterials.DANDELION.canAttachTo(around, BlockFace.TOP)) { aboveAround.setMaterial(VanillaMaterials.DANDELION); shouldConsume = true; } } else { if (VanillaMaterials.ROSE.canAttachTo(around, BlockFace.TOP)) { aboveAround.setMaterial(VanillaMaterials.ROSE); shouldConsume = true; } } } } } if (!PlayerUtil.isCostSuppressed(entity) && shouldConsume) { inv.addAmount(-1); } } }
@Override public long getSpreadingTime(Block b) { return 60000L + GenericMath.getRandom().nextInt(60000) * 3; }
@Override public SpoutBlock getBlock(float x, float y, float z) { return this.getBlock(GenericMath.floor(x), GenericMath.floor(y), GenericMath.floor(z)); }
protected long getGrowthTime(Block block) { return 10000L + GenericMath.getRandom().nextInt(60000); }