use of net.countercraft.movecraft.processing.effects.Effect in project Movecraft by APDevTeam.
the class DetectionTask method get.
@Override
public Effect get() {
frontier();
if (!illegal.isEmpty())
return null;
var result = COMPLETION_VALIDATORS.stream().reduce(DetectionPredicate::and).orElse((a, b, c, d) -> Result.fail()).validate(materials, type, movecraftWorld, player);
result = result.isSucess() ? VISITED_VALIDATORS.stream().reduce(DetectionPredicate::and).orElse((a, b, c, d) -> Result.fail()).validate(visitedMaterials, type, movecraftWorld, player) : result;
if (!result.isSucess()) {
String message = result.getMessage();
return () -> audience.sendMessage(Component.text(message));
}
var hitbox = new BitmapHitBox(legal);
var parents = findParents(hitbox);
var supplied = supplier.apply(type, world, player, parents);
result = supplied.getLeft();
Craft craft = supplied.getRight();
if (type.getBoolProperty(CraftType.MUST_BE_SUBCRAFT) && !(craft instanceof SubCraft)) {
result = Result.failWithMessage(I18nSupport.getInternationalisedString("Detection - Must Be Subcraft"));
}
if (!result.isSucess()) {
String message = result.getMessage();
return () -> audience.sendMessage(Component.text(message));
}
craft.setAudience(audience);
craft.setHitBox(hitbox);
craft.setFluidLocations(new BitmapHitBox(fluid));
craft.setOrigBlockCount(craft.getHitBox().size());
final CraftDetectEvent event = new CraftDetectEvent(craft, startLocation);
WorldManager.INSTANCE.executeMain(() -> Bukkit.getPluginManager().callEvent(event));
if (event.isCancelled())
return () -> craft.getAudience().sendMessage(Component.text(event.getFailMessage()));
return ((Effect) () -> {
// Notify player and console
craft.getAudience().sendMessage(Component.text(String.format("%s Size: %s", I18nSupport.getInternationalisedString("Detection - Successfully piloted craft"), craft.getHitBox().size())));
Movecraft.getInstance().getLogger().info(String.format(I18nSupport.getInternationalisedString("Detection - Success - Log Output"), player == null ? "null" : player.getName(), craft.getType().getStringProperty(CraftType.NAME), craft.getHitBox().size(), craft.getHitBox().getMinX(), craft.getHitBox().getMinZ()));
}).andThen(// TODO: Remove
water(craft)).andThen(// Fire off pilot event
() -> Bukkit.getServer().getPluginManager().callEvent(new CraftPilotEvent(craft, CraftPilotEvent.Reason.PLAYER))).andThen(// Apply post detection effect
postDetection.apply(craft)).andThen(// Add craft to CraftManager
() -> CraftManager.getInstance().add(craft));
}
use of net.countercraft.movecraft.processing.effects.Effect in project Movecraft by APDevTeam.
the class TranslationTask method get.
@Override
public Effect get() {
var preTranslationResult = preTranslationValidators.stream().reduce(MonadicPredicate::and).orElseThrow().validate(craft);
if (!preTranslationResult.isSucess()) {
return () -> craft.getAudience().sendMessage(Component.text(preTranslationResult.getMessage()));
}
var preTranslateEvent = WorldManager.INSTANCE.executeMain(() -> {
var event = new CraftPreTranslateEvent(craft, translation.getX(), translation.getY(), translation.getZ(), craft.getWorld());
Bukkit.getServer().getPluginManager().callEvent(event);
return event;
});
if (preTranslateEvent.isCancelled()) {
return () -> craft.getAudience().sendMessage(Component.text(preTranslateEvent.getFailMessage()));
}
translation = new MovecraftLocation(preTranslateEvent.getDx(), preTranslateEvent.getDy(), preTranslateEvent.getDz());
destinationWorld = CachedMovecraftWorld.of(preTranslateEvent.getWorld());
// TODO: Portal movement
// TODO: Gravity
var destinationLocations = new SetHitBox();
var collisions = new SetHitBox();
var phaseLocations = new SetHitBox();
var harvestLocations = new SetHitBox();
var fuelSources = new ArrayList<FurnaceInventory>();
for (var originLocation : craft.getHitBox()) {
var originMaterial = craft.getMovecraftWorld().getMaterial(originLocation);
// Remove air from hitboxes
if (originMaterial.isAir())
continue;
if (Tags.FURNACES.contains(originMaterial)) {
var state = craft.getMovecraftWorld().getState(originLocation);
if (state instanceof FurnaceInventory)
fuelSources.add((FurnaceInventory) state);
}
var destination = originLocation.add(translation);
destinationLocations.add(destination);
// previous locations cannot collide
if (craft.getMovecraftWorld().equals(destinationWorld) && craft.getHitBox().contains(destination)) {
continue;
}
var destinationMaterial = destinationWorld.getMaterial(destination);
if (craft.getType().getMaterialSetProperty(CraftType.PASSTHROUGH_BLOCKS).contains(destinationMaterial)) {
phaseLocations.add(destination);
continue;
}
if (craft.getType().getMaterialSetProperty(CraftType.HARVEST_BLOCKS).contains(destinationMaterial) && craft.getType().getMaterialSetProperty(CraftType.HARVESTER_BLADE_BLOCKS).contains(originMaterial)) {
harvestLocations.add(destination);
continue;
}
collisions.add(destination);
}
double fuelBurnRate = (double) craft.getType().getPerWorldProperty(CraftType.PER_WORLD_FUEL_BURN_RATE, preTranslateEvent.getWorld());
Effect fuelBurnEffect;
if (craft.getBurningFuel() >= fuelBurnRate) {
// call event
final FuelBurnEvent event = new FuelBurnEvent(craft, craft.getBurningFuel(), fuelBurnRate);
submitEvent(event);
fuelBurnEffect = () -> craft.setBurningFuel(event.getBurningFuel() - event.getFuelBurnRate());
} else {
var fuelSource = findFuelHolders(craft.getType(), fuelSources);
if (fuelSource == null) {
return () -> craft.getAudience().sendMessage(I18nSupport.getInternationalisedComponent("Translation - Failed Craft out of fuel"));
}
callFuelEvent(craft, findFuelStack(craft.getType(), fuelSource));
// TODO: Take Fuel
fuelBurnEffect = () -> Bukkit.getLogger().info("This is where we'd take ur fuel, if we had some");
}
var translationResult = translationValidators.stream().reduce(TetradicPredicate::and).orElseThrow().validate(translation, destinationWorld, destinationLocations, craft.getType());
if (!translationResult.isSucess()) {
return () -> craft.getAudience().sendMessage(Component.text(translationResult.getMessage()));
}
// Direct float comparison due to check for statically initialized value
callCollisionEvent(craft, collisions, preTranslateEvent.getWorld());
if (craft.getType().getFloatProperty(CraftType.COLLISION_EXPLOSION) <= 0F && !collisions.isEmpty()) {
// TODO: collision highlights
return () -> craft.getAudience().sendMessage(Component.text(String.format(I18nSupport.getInternationalisedString("Translation - Failed Craft is obstructed") + " @ %d,%d,%d,%s", 0, 0, 0, "not_implemented")));
}
Effect fluidBoxEffect = fluidBox(craft, translation);
var translateEvent = callTranslateEvent(craft, destinationLocations, preTranslateEvent.getWorld());
// TODO: Sinking?
// TODO: Collision explosion
// TODO: phase blocks
Effect movementEffect = moveCraft();
// TODO: un-phase blocks
Effect teleportEffect = new TeleportationEffect(craft, translation, translateEvent.getWorld());
return fuelBurnEffect.andThen(fluidBoxEffect).andThen(movementEffect).andThen(teleportEffect);
}
use of net.countercraft.movecraft.processing.effects.Effect in project Movecraft by APDevTeam.
the class WorldManager method run.
public void run() {
if (!Bukkit.isPrimaryThread()) {
throw new RuntimeException("WorldManager must be executed on the main thread.");
}
if (tasks.isEmpty())
return;
running = true;
int remaining = tasks.size();
List<CompletableFuture<Effect>> inProgress = new ArrayList<>();
while (!tasks.isEmpty()) {
inProgress.add(CompletableFuture.supplyAsync(tasks.poll()).whenComplete((effect, exception) -> {
poison();
if (exception != null) {
exception.printStackTrace();
} else if (effect != null) {
worldChanges.add(effect);
}
}));
}
// process pre-queued tasks and their requests to the main thread
eventLoop: while (true) {
var runningTasks = new ArrayList<Runnable>();
try {
runningTasks.add(currentTasks.poll(5, TimeUnit.SECONDS));
} catch (InterruptedException e) {
continue;
}
if (runningTasks.isEmpty()) {
Bukkit.getLogger().severe("WorldManager timed out on task query! Dumping " + inProgress.size() + " tasks.");
inProgress.forEach(task -> task.cancel(true));
worldChanges.clear();
break;
}
currentTasks.drainTo(runningTasks);
for (var runnable : runningTasks) {
if (runnable == POISON) {
remaining--;
if (remaining == 0) {
break eventLoop;
}
}
runnable.run();
}
}
// process world updates on the main thread
Effect sideEffect;
while ((sideEffect = worldChanges.poll()) != null) {
sideEffect.run();
}
CachedMovecraftWorld.purge();
running = false;
}
Aggregations