private void renderBlocks(MatchTeam matchTeam) { byte color1 = progressingTowardsTeam != null ? ColorConverter.convertChatColorToDyeColor(progressingTowardsTeam.getColor()).getWoolData() : -1; byte color2 = controller != null && matchTeam == controller ? ColorConverter.convertChatColorToDyeColor(controller.getColor()).getWoolData() : -1; Location center = region.getCenter(); double x = center.getX(); double z = center.getZ(); double percent = Math.toRadians(getPercent() * 3.6); for(Block block : region.getBlocks()) { if(!Blocks.isVisualMaterial(block.getType())) continue; double dx = block.getX() - x; double dz = block.getZ() - z; double angle = Math.atan2(dz, dx); if(angle < 0) angle += 2 * Math.PI; byte color = angle < percent ? color1 : color2; if (color == -1) { Pair<Material,Byte> oldBlock = regionSave.getBlockAt(new BlockVector(block.getLocation().toVector())); if (oldBlock.getLeft().equals(block.getType())) color = oldBlock.getRight(); } if (color != -1) { block.setData(color); // Bukkit.broadcastMessage("set to " + color); } else { // Bukkit.broadcastMessage("color = -1"); } } }
public static BlockVector parseBlockVector(Node node, BlockVector def) throws InvalidXMLException { if(node == null) return def; String[] components = node.getValue().trim().split("\\s*,\\s*"); if(components.length != 3) { throw new InvalidXMLException("Invalid block location", node); } try { return new BlockVector(Integer.parseInt(components[0]), Integer.parseInt(components[1]), Integer.parseInt(components[2])); } catch(NumberFormatException e) { throw new InvalidXMLException("Invalid block location", node); } }
public FiniteBlockRegion(Collection<BlockVector> positions) { this.positions = BlockVectorSet.of(positions); // calculate AABB final Vector min = new Vector(Double.MAX_VALUE); final Vector max = new Vector(-Double.MAX_VALUE); for(BlockVector pos : this.positions) { min.setX(Math.min(min.getX(), pos.getBlockX())); min.setY(Math.min(min.getY(), pos.getBlockY())); min.setZ(Math.min(min.getZ(), pos.getBlockZ())); max.setX(Math.max(max.getX(), pos.getBlockX() + 1)); max.setY(Math.max(max.getY(), pos.getBlockY() + 1)); max.setZ(Math.max(max.getZ(), pos.getBlockZ() + 1)); } this.bounds = Cuboid.between(min, max); }
/** * Change the controller display to the given team's color, or reset the display if team is null */ @SuppressWarnings("deprecation") public void setController(Competitor controllingTeam) { if(!Objects.equals(this.controllingTeam, controllingTeam) && this.controllerDisplayRegion != null) { if(controllingTeam == null) { for(BlockVector block : this.controllerDisplayRegion.getBlockVectors()) { this.controllerDisplayImage.restore(block); } } else { byte blockData = BukkitUtils.chatColorToDyeColor(controllingTeam.getColor()).getWoolData(); for(BlockVector pos : this.controllerDisplayRegion.getBlockVectors()) { BlockUtils.blockAt(match.getWorld(), pos).setData(blockData); } } this.controllingTeam = controllingTeam; } }
protected void setProgress(Competitor controllingTeam, Competitor capturingTeam, double capturingProgress) { if(this.progressDisplayRegion != null) { Vector center = this.progressDisplayRegion.getBounds().center(); // capturingProgress can be zero, but it can never be one, so invert it to avoid // a zero-area SectorRegion that can cause glitchy rendering SectorRegion sectorRegion = new SectorRegion(center.getX(), center.getZ(), 0, (1 - capturingProgress) * 2 * Math.PI); for(BlockVector pos : this.progressDisplayRegion.getBlockVectors()) { if(sectorRegion.contains(pos)) { this.setBlock(pos, controllingTeam); } else { this.setBlock(pos, capturingTeam); } } } }
boolean renew(BlockVector pos) { MaterialData material; if(isOriginalShuffleable(pos)) { // If position is shuffled, first try to find a nearby shuffleable block to swap with. // This helps to make shuffling less predictable when the material deficit is small or // out of proportion to the original distribution of materials. material = sampleShuffledMaterial(pos); // If that fails, choose a random material, weighted by the current material deficits. if(material == null) material = chooseShuffledMaterial(); } else { material = snapshot().getOriginalMaterial(pos); } if(material != null) { return renew(pos, material); } return false; }
boolean renew(BlockVector pos, MaterialData material) { // We need to do the entity check here rather than canRenew, because we are not // notified when entities move in our out of the way. if(!isClearOfEntities(pos)) return false; Location location = pos.toLocation(match.getWorld()); Block block = location.getBlock(); BlockState newState = location.getBlock().getState(); newState.setMaterialData(material); BlockRenewEvent event = new BlockRenewEvent(block, newState, this); match.callEvent(event); // Our own handler will get this and remove the block from the pool if(event.isCancelled()) return false; newState.update(true, true); if(definition.particles) { NMSHacks.playBlockBreakEffect(match.getWorld(), pos, material.getItemType()); } if(definition.sound) { NMSHacks.playBlockPlaceSound(match.getWorld(), pos, material.getItemType(), 1f); } return true; }
@Override public Iterator<BlockVector> iterator() { final TLongIterator iter = this.set.iterator(); return new Iterator<BlockVector>() { @Override public boolean hasNext() { return iter.hasNext(); } @Override public BlockVector next() { return decodePos(iter.next()); } @Override public void remove() { iter.remove(); } }; }
/** * Return an iterator that reuses a single BlockVector instance, * mutating it for each iteration. */ public Iterator<BlockVector> mutableIterator() { final TLongIterator iter = set.iterator(); return new Iterator<BlockVector>() { final BlockVector value = new BlockVector(); @Override public boolean hasNext() { return iter.hasNext(); } @Override public BlockVector next() { return decodePos(iter.next(), value); } }; }
@Override public Iterator<BlockVector> iterator() { int spacing = 20; List<BlockVector> result = new ArrayList<>(spacing); double PI2 = Math.PI * 2.0; for (int i = 0; i <= spacing; i++) { double angle = ((double) i / spacing) * PI2; double dX = Math.cos(angle) * this.radius + this.base.getX(); double dZ = Math.sin(angle) * this.radius + this.base.getZ(); // TODO Height 1 currently counts two separate heights, should it stay like that? for (int j = 0; j <= (int) this.height; j++) { result.add(new BlockVector(dX, this.base.getY() + j, dZ)); } } return result.iterator(); }
@Override public BlockVector next() { if (!hasNext()) { throw new NoSuchElementException(); } BlockVector answer = new BlockVector(nextX, nextY, nextZ); if (++nextX > max.getBlockX()) { nextX = min.getBlockX(); if (++nextY > max.getBlockY()) { nextY = min.getBlockY(); if (++nextZ > max.getBlockZ()) { nextX = Integer.MIN_VALUE; } } } return answer; }
@Override public Iterator<BlockVector> iterator() { return new Iterator<BlockVector>() { boolean done; @Override public boolean hasNext() { return !done; } @Override public BlockVector next() { if (this.done) { throw new NoSuchElementException(); } this.done = true; return BlockExtent.this.vector.toBlockVector(); } }; }
@Override public void enable() { Runnable runnable = () -> { for (Extent extent : data.extents) { for (BlockVector bv : extent) { bv.toLocation(getSession().getWorld()).getBlock().setTypeIdAndData(data.blockData.getItemTypeId(), data.blockData.getData(), data.physics); } } }; // If a delay or interval has been set, create a future task if (data.delay != null || data.interval != null) { newTask().run(runnable).delay(data.delay).interval(data.interval).build(); } else { // Otherwise, just run this module now runnable.run(); } }
public boolean contain(BlockData blockData) { // First do a sanity check with the map // Currently, we don't replace blocks! if (contains(blockData)) return false; // Check the world name if (worldName != null && !worldName.equals(blockData.getWorldName())) return false; // Set a world name if this block list doesn't have one yet if (worldName == null || worldName.length() == 0) worldName = blockData.getWorldName(); BlockVector blockLocation = blockData.getPosition(); contain(blockLocation); return true; }
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) public void onBlockBreak(BlockBreakEvent event) { final Player player = event.getPlayer(); long time = timer.getTicks(); // Start tracking this broken block final BrokenBlock brokenBlock = new BrokenBlock(event.getBlock(), player, time); final BlockVector bv = new BlockVector(brokenBlock.block.getLocation().toVector()); brokenBlocks.put(bv, brokenBlock); // Schedule the tracking to end after MAX_SPLEEF_TIME new SchedulerUtil() { public void runnable() { if (brokenBlocks.containsKey(bv) && brokenBlocks.get(bv) == brokenBlock) { brokenBlocks.remove(bv); } } }.laterAsync(MAX_SPLEEF_TIME + 1); }
public RegionSave(RegionModule region) { BlockVector min = blockAlign(region.getMin()); BlockVector max = blockAlign(region.getMax()); BlockVector size = max.minus(min).toBlockVector(); this.min = min; this.size = size; List<Pair<Material,Byte>> blocks = new ArrayList<>(); for (int z = min.getBlockZ(); z < max.getBlockZ(); z++) { for (int y = min.getBlockY(); y < max.getBlockY(); y++) { for (int x = min.getBlockX(); x < max.getBlockX(); x++) { Block block = new Location(GameHandler.getGameHandler().getMatchWorld(), x, y, z).getBlock(); blocks.add(new ImmutablePair<>(block.getType(), block.getData())); } } } this.blocks = blocks; }
private void renderBlocks() { if (progress == null) return; byte color1 = capturingTeam != null ? MiscUtil.convertChatColorToDyeColor(capturingTeam.getColor()).getWoolData() : -1; byte color2 = team != null ? MiscUtil.convertChatColorToDyeColor(team.getColor()).getWoolData() : -1; Vector center = progress.getCenterBlock().getVector(); double x = center.getX(); double z = center.getZ(); double percent = Math.toRadians(getPercent() * 3.6); for(Block block : progress.getBlocks()) { if (!visualMaterials.evaluate(block).equals(FilterState.ALLOW)) continue; double dx = block.getX() - x; double dz = block.getZ() - z; double angle = Math.atan2(dz, dx); if(angle < 0) angle += 2 * Math.PI; byte color = angle < percent ? color1 : color2; if (color == -1) { Pair<Material,Byte> oldBlock = oldProgress.getBlockAt(new BlockVector(block.getLocation().position())); if (oldBlock.getLeft().equals(block.getType())) color = oldBlock.getRight(); } if (color != -1) block.setData(color); } }
@EventHandler public void onBlockRedstone(BlockRedstoneEvent event) { if (event.getOldCurrent() != 0 || event.getNewCurrent() == 0) { return; } Block block = event.getBlock(); World world = block.getWorld(); String worldName = world.getName(); Map<BlockVector, BankSet> worldInteresting = bankInfo.get(worldName); if (worldInteresting == null) { worldInteresting = buildWorldInteresting(worldName); bankInfo.put(worldName, worldInteresting); } BlockVector target = new BlockVector(block.getX(), block.getY(), block.getZ()); BankSet targetBank = worldInteresting.get(target); if (targetBank != null) { targetBank.shelveItems(world); } }
public ChestManager(Block block, boolean allow_restack) { this.setRestackAllowed(allow_restack); chest1 = block.getLocation().toVector().toBlockVector(); for (BlockFace face: cardinals) { Block other = block.getRelative(face); if (other.getType() == block.getType()) { BlockVector othervec = other.getLocation().toVector().toBlockVector(); if (face == BlockFace.NORTH || face == BlockFace.EAST) { chest2 = chest1; chest1 = othervec; } else { chest2 = othervec; } break; } } }
private void clearDuplicates(ChestManager newmanager) { // Deal with a specialty case if we add a double chest where there was // previously a single, or vice versa. if (newmanager.getChest2() != null) { ChestManager reversi = new ChestManager(newmanager.getChest2(), newmanager.getChest1(), false); chestLocations.remove(reversi); for (BlockVector vec : newmanager.internalBlockLocations()) { ChestManager test = new ChestManager(vec, null, false); chestLocations.remove(test); } } else { BlockVector candidate = newmanager.getChest1(); for (ChestManager cm : chestLocations) { if (candidate.equals(cm.getChest1()) || candidate.equals(cm.getChest2())) { chestLocations.remove(cm); break; } } } }
@Override protected Inventory[] validInventories(ChestManager manager, World world) { Inventory i1 = manager.getInventory(world, manager.getChest1()); if (i1 == null) return new Inventory[0]; if (i1.getSize() == DOUBLE_CHEST_SIZE) { return new Inventory[] { i1 }; } else if (i1.getSize() != SINGLE_CHEST_SIZE) { for (String line: MondoConstants.BAD_CHEST_WARNING) { MondoConfig.getLog().warning("MondoChest: " + line); } return new Inventory[0]; } Inventory i2 = null; BlockVector chest2 = manager.getChest2(); if (chest2 != null) { i2 = manager.getInventory(world, chest2); } if (i2 == null) return new Inventory[] { i1 }; return new Inventory[] { i1, i2 }; }
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) public void applyEffects(final CoarsePlayerMoveEvent event) { MatchPlayer player = this.match.getPlayer(event.getPlayer()); if(player == null) return; final BlockVector from = event.getBlockFrom().toBlockVector(); final BlockVector to = event.getBlockTo().toBlockVector(); for(EventRule rule : this.ruleContext.get(EventRuleScope.EFFECT)) { if(rule.velocity() == null && rule.kit() == null) continue; boolean enters = rule.region().enters(from, to); boolean exits = rule.region().exits(from, to); if(!enters && !exits) continue; if(!player.canInteract() || rule.filter() == null || rule.filter().query(player) != QueryResponse.DENY) { // Note: works on observers if(enters && rule.velocity() != null) { event.getPlayer().setVelocity(rule.velocity()); } if(rule.kit() != null && player.canInteract()) { if(enters) { player.facet(KitPlayerFacet.class).applyKit(rule.kit(), false); } if(exits && rule.lendKit()) { rule.kit().remove(player); } } } } }
/** * Return the subset of rules that may act on the given region */ public BlockDropsRuleSet subsetAffecting(FiniteBlockRegion region) { ImmutableList.Builder<BlockDropsRule> subset = ImmutableList.builder(); for(BlockDropsRule rule : this.rules) { for(BlockVector block : region.getBlockVectors()) { if(rule.region == null || rule.region.contains(block)) { subset.add(rule); break; } } } return new BlockDropsRuleSet(subset.build()); }
@Deprecated default Iterator<BlockVector> getBlockVectorIterator() { return Iterators.transform( blockRegion().mutableIterator(), BlockVector::new ); }
@Override public Vector getRandom(Random random) { final BlockVector randomBlock = positions.chooseRandom(random); double dx = random.nextDouble(); double dy = random.nextDouble(); double dz = random.nextDouble(); return randomBlock.add(dx, dy, dz); }
private void setBlock(BlockVector pos, Competitor team) { final Block block = BlockUtils.blockAt(match.getWorld(), pos); if(this.controlPoint.getDefinition().getVisualMaterials().query(new BlockQuery(block)).isAllowed()) { if(team != null) { block.setData(BukkitUtils.chatColorToDyeColor(team.getColor()).getWoolData()); } else { this.progressDisplayImage.restore(pos); } } }
boolean isOriginalRenewable(BlockVector pos) { if(!definition.region.contains(pos)) return false; Filter.QueryResponse response = renewableCache.get(pos); if(response == null) { response = definition.renewableBlocks.query(new BlockQuery(snapshot().getOriginalBlock(pos))); } return response.isAllowed(); }
boolean isOriginalShuffleable(BlockVector pos) { if(!definition.region.contains(pos)) return false; Filter.QueryResponse response = shuffleableCache.get(pos); if(response == null) { response = definition.shuffleableBlocks.query(new BlockQuery(snapshot().getOriginalBlock(pos))); } return response.isAllowed(); }
boolean isNew(BlockState currentState) { // If original block does not match renewable rule, block is new BlockVector pos = BlockUtils.position(currentState); if(!isOriginalRenewable(pos)) return true; // If original and current material are both shuffleable, block is new MaterialData currentMaterial = currentState.getMaterialData(); if(isOriginalShuffleable(pos) && definition.shuffleableBlocks.query(new BlockQuery(currentState)).isAllowed()) return true; // If current material matches original, block is new if(currentMaterial.equals(snapshot().getOriginalMaterial(pos))) return true; // Otherwise, block is not new (can be renewed) return false; }
MaterialData sampleShuffledMaterial(BlockVector pos) { Random random = match.getRandom(); int range = SHUFFLE_SAMPLE_RANGE; int diameter = range * 2 + 1; for(int i = 0; i < SHUFFLE_SAMPLE_ITERATIONS; i++) { BlockState block = snapshot().getOriginalBlock(pos.getBlockX() + random.nextInt(diameter) - range, pos.getBlockY() + random.nextInt(diameter) - range, pos.getBlockZ() + random.nextInt(diameter) - range); if(definition.shuffleableBlocks.query(new BlockQuery(block)).isAllowed()) return block.getMaterialData(); } return null; }
private int offset(BlockVector pos) { if(!this.bounds.containsBlock(pos)) { throw new IndexOutOfBoundsException("Block is not inside this BlockImage"); } return (pos.coarseZ() - this.origin.coarseZ()) * this.size.coarseX() * this.size.coarseY() + (pos.coarseY() - this.origin.coarseY()) * this.size.coarseX() + (pos.coarseX() - this.origin.coarseX()); }
@SuppressWarnings("deprecation") public BlockState getState(BlockVector pos) { int offset = this.offset(pos); BlockState state = pos.toLocation(this.world).getBlock().getState(); state.setTypeId(this.blockIds[offset]); state.setRawData(this.blockData[offset]); return state; }
/** * Copy the block at the given position from the image to the world * @param pos Block position in world coordinates */ @SuppressWarnings("deprecation") public void restore(BlockVector pos) { int offset = this.offset(pos); pos.toLocation(this.world).getBlock().setTypeIdAndData(this.blockIds[offset], this.blockData[offset], true); }
public MaterialData getOriginalMaterial(int x, int y, int z) { if(y < 0 || y >= 256) return new MaterialData(Material.AIR); ChunkVector chunkVector = ChunkVector.ofBlock(x, y, z); ChunkSnapshot chunkSnapshot = chunkSnapshots.get(chunkVector); if(chunkSnapshot != null) { BlockVector chunkPos = chunkVector.worldToChunk(x, y, z); return new MaterialData(chunkSnapshot.getBlockTypeId(chunkPos.getBlockX(), chunkPos.getBlockY(), chunkPos.getBlockZ()), (byte) chunkSnapshot.getBlockData(chunkPos.getBlockX(), chunkPos.getBlockY(), chunkPos.getBlockZ())); } else { return getMatch().getWorld().getBlockAt(x, y, z).getState().getMaterialData(); } }
public BlockState getOriginalBlock(int x, int y, int z) { BlockState state = getMatch().getWorld().getBlockAt(x, y, z).getState(); if(y < 0 || y >= 256) return state; ChunkVector chunkVector = ChunkVector.ofBlock(x, y, z); ChunkSnapshot chunkSnapshot = chunkSnapshots.get(chunkVector); if(chunkSnapshot != null) { BlockVector chunkPos = chunkVector.worldToChunk(x, y, z); state.setMaterialData(new MaterialData(chunkSnapshot.getBlockTypeId(chunkPos.getBlockX(), chunkPos.getBlockY(), chunkPos.getBlockZ()), (byte) chunkSnapshot.getBlockData(chunkPos.getBlockX(), chunkPos.getBlockY(), chunkPos.getBlockZ()))); } return state; }
@Override Entry<BlockVector, MaterialData> castEntry(Object obj) { if(!(obj instanceof Entry)) return null; Entry entry = (Entry) obj; if(entry.getKey() instanceof BlockVector && entry.getValue() instanceof MaterialData) { return (Entry<BlockVector, MaterialData>) entry; } else { return null; } }