Added radius-render command and some small improvements

This commit is contained in:
Blue (Lukas Rieger) 2020-02-06 19:26:51 +01:00
parent e3500de150
commit 190d65ca7f
9 changed files with 118 additions and 52 deletions

View File

@ -11,6 +11,7 @@
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import com.flowpowered.math.vector.Vector2i;
import com.flowpowered.math.vector.Vector3i;
import de.bluecolored.bluemap.common.plugin.Commands;
@ -75,27 +76,40 @@ public boolean execute(CommandSender sender, CommandSource source, String[] args
commands.add(new Command("bluemap.rendertask.create.world", "render") {
@Override
public boolean execute(CommandSender sender, CommandSource source, String[] args) {
if (args.length > 1) return false;
World world;
if (args.length == 1) {
world = Bukkit.getWorld(args[0]);
if (world == null) {
source.sendMessage(Text.of(TextColor.RED, "There is no world named '" + args[0] + "'!"));
return true;
if (sender instanceof Player) {
if (args.length > 2) return false;
Player player = (Player) sender;
World world = null;
int radius = -1;
if (args.length >= 1) {
world = Bukkit.getWorld(args[0]);
}
} else {
if (sender instanceof Player) {
Player player = (Player) sender;
if (args.length == 2 || (args.length == 1 && world == null)) {
try {
radius = Integer.parseInt(args[args.length - 1]);
} catch (NumberFormatException ex) {
return false;
}
}
if (world == null){
world = player.getWorld();
} else {
source.sendMessage(Text.of(TextColor.RED, "Since you are not a player, you have to specify a world!"));
return true;
}
if (radius >= 0) {
Vector2i pos = new Vector2i(player.getLocation().getBlockX(), player.getLocation().getBlockZ());
bluemapCommands.executeRenderWorldCommand(source, world.getUID(), pos, radius);
} else {
bluemapCommands.executeRenderWorldCommand(source, world.getUID());
}
return true;
} else {
if (args.length != 1) return false;
World world = Bukkit.getWorld(args[0]);
bluemapCommands.executeRenderWorldCommand(source, world.getUID());
return true;
}
bluemapCommands.executeRenderWorldCommand(source, world.getUID());
return true;
}
});

View File

@ -14,7 +14,7 @@ commands:
/<command> reload
/<command> pause
/<command> resume
/<command> render [world]
/<command> render [world] [block-radius]
/<command> debug
permissions:
bluemap.*:

View File

@ -171,6 +171,7 @@ public void renderMaps() throws IOException {
Logger.global.logInfo("Found unfinished render, continuing ... (If you want to start a new render, delete the this file: " + rmstate.getCanonicalPath());
} catch (IOException ex) {
Logger.global.logError("Failed to read saved render-state! Remove the file " + rmstate.getCanonicalPath() + " to start a new render.", ex);
return;
}
} else {
for (MapType map : maps.values()) {

View File

@ -5,6 +5,7 @@
import java.util.Collection;
import java.util.List;
import java.util.UUID;
import java.util.function.Predicate;
import org.apache.commons.lang3.time.DurationFormatUtils;
@ -154,10 +155,18 @@ public boolean executeResumeCommand(CommandSource source) {
}
}
/**
* Command: /bluemap render [world]
*/
public boolean executeRenderWorldCommand(CommandSource source, UUID worldUuid) {
return executeRenderWorldCommand(source, worldUuid, null, -1);
}
/**
* Command: /bluemap render [world] [block-radius]
*/
public boolean executeRenderWorldCommand(CommandSource source, UUID worldUuid, Vector2i center, int blockRadius) {
if (!checkLoaded(source)) return false;
World world = bluemap.getWorld(worldUuid);
@ -170,7 +179,7 @@ public boolean executeRenderWorldCommand(CommandSource source, UUID worldUuid) {
world.invalidateChunkCache();
new Thread(() -> {
createWorldRenderTask(source, world);
createWorldRenderTask(source, world, center, blockRadius);
}).start();
return true;
@ -262,9 +271,21 @@ private Text createPrioritizeTaskText(RenderTask task) {
return Text.of(TextColor.GREEN, "[^]").setHoverText(Text.of(TextColor.GRAY, "click to prioritize this render-task")).setClickCommand("/bluemap render prioritize " + task.getUuid());
}
private void createWorldRenderTask(CommandSource source, World world) {
private void createWorldRenderTask(CommandSource source, World world, Vector2i center, long blockRadius) {
source.sendMessage(Text.of(TextColor.GOLD, "Collecting chunks to render..."));
Collection<Vector2i> chunks = world.getChunkList();
String taskName = "world-render";
Predicate<Vector2i> filter;
if (center == null || blockRadius < 0) {
filter = c -> true;
} else {
filter = c -> c.mul(16).distanceSquared(center) <= blockRadius * blockRadius;
taskName = "radius-render";
}
Collection<Vector2i> chunks = world.getChunkList(filter);
source.sendMessage(Text.of(TextColor.GREEN, chunks.size() + " chunks found!"));
for (MapType map : bluemap.getMapTypes()) {
@ -274,8 +295,8 @@ private void createWorldRenderTask(CommandSource source, World world) {
HiresModelManager hmm = map.getTileRenderer().getHiresModelManager();
Collection<Vector2i> tiles = hmm.getTilesForChunks(chunks);
RenderTask task = new RenderTask("world-render", map);
RenderTask task = new RenderTask(taskName, map);
task.addTiles(tiles);
task.optimizeQueue();
bluemap.getRenderManager().addRenderTask(task);

View File

@ -41,6 +41,7 @@
import java.util.Objects;
import java.util.UUID;
import java.util.concurrent.ExecutionException;
import java.util.function.Predicate;
import com.flowpowered.math.vector.Vector2i;
import com.flowpowered.math.vector.Vector3i;
@ -245,7 +246,7 @@ public boolean isChunkGenerated(Vector2i chunkPos) throws IOException {
}
@Override
public Collection<Vector2i> getChunkList(long modifiedSinceMillis){
public Collection<Vector2i> getChunkList(long modifiedSinceMillis, Predicate<Vector2i> filter){
List<Vector2i> chunks = new ArrayList<>(10000);
if (!getRegionFolder().toFile().isDirectory()) return Collections.emptyList();
@ -274,7 +275,12 @@ public Collection<Vector2i> getChunkList(long modifiedSinceMillis){
timestamp |= (raf.read() & 0xFF) << 8;
timestamp |= raf.read() & 0xFF;
if (timestamp >= (modifiedSinceMillis / 1000)) chunks.add(new Vector2i(rX * 32 + x, rZ * 32 + z));
if (timestamp >= (modifiedSinceMillis / 1000)) {
Vector2i chunk = new Vector2i(rX * 32 + x, rZ * 32 + z);
if (filter.test(chunk)) {
chunks.add(chunk);
}
}
}
}
} catch (Exception ex) {

View File

@ -25,9 +25,9 @@
package de.bluecolored.bluemap.core.world;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.UUID;
import java.util.function.Predicate;
import com.flowpowered.math.vector.Vector2i;
import com.flowpowered.math.vector.Vector3i;
@ -98,29 +98,8 @@ public Block getBlock(int x, int y, int z) {
}
@Override
public Collection<Vector2i> getChunkList(){
Collection<Vector2i> chunkList = world.getChunkList();
ArrayList<Vector2i> filteredChunkList = new ArrayList<>(chunkList.size());
for (Vector2i chunk : chunkList) {
if (isInside(chunk)) filteredChunkList.add(chunk);
}
filteredChunkList.trimToSize();
return filteredChunkList;
}
@Override
public Collection<Vector2i> getChunkList(long modifiedSince) {
Collection<Vector2i> chunkList = world.getChunkList(modifiedSince);
ArrayList<Vector2i> filteredChunkList = new ArrayList<>(chunkList.size());
for (Vector2i chunk : chunkList) {
if (isInside(chunk)) filteredChunkList.add(chunk);
}
filteredChunkList.trimToSize();
return filteredChunkList;
public Collection<Vector2i> getChunkList(long modifiedSince, Predicate<Vector2i> filter) {
return world.getChunkList(modifiedSince, filter.and(chunk -> isInside(chunk)));
}
@Override

View File

@ -27,6 +27,7 @@
import java.io.IOException;
import java.util.Collection;
import java.util.UUID;
import java.util.function.Predicate;
import com.flowpowered.math.vector.Vector2i;
import com.flowpowered.math.vector.Vector3i;
@ -73,14 +74,30 @@ default Block getBlock(int x, int y, int z) {
* <i>(Be aware that the collection is not cached and recollected each time from the world-files!)</i>
*/
public default Collection<Vector2i> getChunkList(){
return getChunkList(0);
return getChunkList(0, c -> true);
}
/**
* Returns a filtered collection of all generated chunks.<br>
* <i>(Be aware that the collection is not cached and recollected each time from the world-files!)</i>
*/
public default Collection<Vector2i> getChunkList(Predicate<Vector2i> filter){
return getChunkList(0, filter);
}
/**
* Returns a collection of all chunks that have been modified at or after the specified timestamp.<br>
* <i>(Be aware that the collection is not cached and recollected each time from the world-files!)</i>
*/
public Collection<Vector2i> getChunkList(long modifiedSince);
public default Collection<Vector2i> getChunkList(long modifiedSince){
return getChunkList(modifiedSince, c -> true);
}
/**
* Returns a filtered collection of all chunks that have been modified at or after the specified timestamp.<br>
* <i>(Be aware that the collection is not cached and recollected each time from the world-files!)</i>
*/
public Collection<Vector2i> getChunkList(long modifiedSince, Predicate<Vector2i> filter);
/**
* Returns true if and only if that chunk is fully generated and no world-generation or lighting has yet to be done.

View File

@ -48,6 +48,7 @@ export default class Position {
.children()
.first();
element.on('input', this.onInput(type));
element.on('keydown', this.onKeyDown);
return element;
}
@ -58,6 +59,10 @@ export default class Position {
}
};
onKeyDown = event => {
event.stopPropagation();
};
onBlueMapUpdateFrame = () => {
const { x, y, z } = this.blueMap.controls.targetPosition;
const values = [ z, y, x ];

View File

@ -85,7 +85,10 @@ public CommandSpec createRenderCommand() {
.childArgumentParseExceptionFallback(false)
.child(createPrioritizeTaskCommand(), "prioritize")
.child(createRemoveTaskCommand(), "remove")
.arguments(GenericArguments.optional(GenericArguments.world(Text.of("world"))))
.arguments(
GenericArguments.optionalWeak(GenericArguments.onlyOne(GenericArguments.world(Text.of("world")))),
GenericArguments.optional(GenericArguments.integer(Text.of("block-radius")))
)
.executor((source, args) -> {
WorldProperties spongeWorld = args.<WorldProperties>getOne("world").orElse(null);
@ -99,6 +102,26 @@ public CommandSpec createRenderCommand() {
return CommandResult.empty();
}
int radius = args.<Integer>getOne("block-radius").orElse(-1);
if (radius >= 0) {
if (source instanceof Locatable) {
Location<org.spongepowered.api.world.World> loc = ((Locatable) source).getLocation();
if (commands.executeRenderWorldCommand(new SpongeCommandSource(source), spongeWorld.getUniqueId(), loc.getBlockPosition().toVector2(true), radius)) {
return CommandResult.success();
} else {
return CommandResult.empty();
}
} else {
source.sendMessages(
Text.of(TextColors.RED, "Could not determine a center-location for the radius!"),
Text.of(TextColors.GRAY, "Could not determine a center-location for the radius!")
);
return CommandResult.empty();
}
}
if (commands.executeRenderWorldCommand(new SpongeCommandSource(source), spongeWorld.getUniqueId())) {
return CommandResult.success();
} else {