start working on error handling stuff

This commit is contained in:
dfsek
2025-12-29 22:18:44 -07:00
parent 9a16336f53
commit cb08401536
76 changed files with 212 additions and 165 deletions
@@ -15,7 +15,7 @@ public class ApiAddon implements BaseAddon {
}
@Override
public Version getVersion() {
public Version version() {
return version;
}
@@ -33,7 +33,7 @@ public class ApiAddonLoader implements BootstrapBaseAddon<BaseAddon> {
}
@Override
public Version getVersion() {
public Version version() {
return VERSION;
}
}
@@ -39,7 +39,7 @@ public class AddonsCommandAddon implements AddonInitializer {
.append(" - ")
.append(addon.getID())
.append('@')
.append(addon.getVersion().getFormatted())
.append(addon.version().getFormatted())
.append('\n'));
context.sender().sendMessage(addons.toString());
})
@@ -52,10 +52,10 @@ public class AddonsCommandAddon implements AddonInitializer {
BaseAddon addon = context.get("addon");
StringBuilder addonInfo = new StringBuilder("Addon ").append(addon.getID()).append('\n');
addonInfo.append("Version: ").append(addon.getVersion().getFormatted()).append('\n');
addonInfo.append("Version: ").append(addon.version().getFormatted()).append('\n');
addonInfo.append("Dependencies:\n");
addon.getDependencies().forEach((id, versions) -> addonInfo
addon.dependencies().forEach((id, versions) -> addonInfo
.append(" - ")
.append(id)
.append('@')
@@ -4,7 +4,6 @@ package com.dfsek.terra.addons.commands.locate;
import com.dfsek.seismic.type.vector.Vector2Int;
import com.dfsek.seismic.type.vector.Vector3Int;
import com.dfsek.terra.api.util.function.FunctionUtils;
import com.dfsek.terra.api.util.generic.data.types.Maybe;
import org.incendo.cloud.CommandManager;
@@ -13,8 +12,6 @@ import org.incendo.cloud.context.CommandContext;
import org.incendo.cloud.description.Description;
import org.incendo.cloud.parser.standard.IntegerParser;
import java.util.Optional;
import com.dfsek.terra.addons.manifest.api.AddonInitializer;
import com.dfsek.terra.api.Platform;
import com.dfsek.terra.api.addon.BaseAddon;
@@ -41,7 +38,7 @@ public class LocateCommandAddon implements AddonInitializer {
private BaseAddon addon;
private static Registry<Biome> getBiomeRegistry(CommandContext<CommandSender> sender) {
return sender.sender().getEntity().orThrow().world().getPack().getRegistry(Biome.class);
return sender.sender().entity().orThrow().world().getPack().getRegistry(Biome.class);
}
@Override
@@ -69,7 +66,7 @@ public class LocateCommandAddon implements AddonInitializer {
.handler(context -> {
// 1. Gather Context & Arguments
Biome targetBiome = context.get("biome");
Entity sender = context.sender().getEntity().orThrow(
Entity sender = context.sender().entity().orThrow(
() -> new Error("Only entities can run this command."));
World world = sender.world();
@@ -34,7 +34,7 @@ public class StructureCommandAddon implements AddonInitializer {
private BaseAddon addon;
private static Registry<Structure> getStructureRegistry(CommandContext<CommandSender> sender) {
return sender.sender().getEntity().orThrow().world().getPack().getRegistry(Structure.class);
return sender.sender().entity().orThrow().world().getPack().getRegistry(Structure.class);
}
@Override
@@ -55,7 +55,7 @@ public class StructureCommandAddon implements AddonInitializer {
.optional("rotation", EnumParser.enumParser(Rotation.class), DefaultValue.constant(Rotation.NONE))
.handler(context -> {
Structure structure = context.get("structure");
Entity sender = context.sender().getEntity().orThrow();
Entity sender = context.sender().entity().orThrow();
structure.generate(
sender.position().toInt(),
sender.world(),
@@ -55,7 +55,7 @@ public class TerraFlora implements Structure {
private void test(EnumSet<Direction> faces, Direction f, Vector3Int b, WritableWorld world) {
if(testRotation.contains(
world.getBlockState(b.getX() + f.getModX(), b.getY() + f.getModY(), b.getZ() + f.getModZ()).getBlockType()))
world.getBlockState(b.getX() + f.getModX(), b.getY() + f.getModY(), b.getZ() + f.getModZ()).blockType()))
faces.add(f);
}
@@ -24,6 +24,6 @@ public class AirMatchPatternTemplate implements ObjectTemplate<Pattern> {
@Override
public Pattern get() {
return new MatchPattern(offset, BlockState::isAir);
return new MatchPattern(offset, BlockState::air);
}
}
@@ -26,6 +26,6 @@ public class BlockSetMatchPatternTemplate implements ObjectTemplate<Pattern> {
@Override
public Pattern get() {
return new MatchPattern(offset, blockState -> blocks.contains(blockState.getBlockType()));
return new MatchPattern(offset, blockState -> blocks.contains(blockState.blockType()));
}
}
@@ -21,6 +21,6 @@ public class SolidMatchPatternTemplate implements ObjectTemplate<Pattern> {
@Override
public Pattern get() {
return new MatchPattern(offset, blockState -> blockState.getBlockType().isSolid());
return new MatchPattern(offset, blockState -> blockState.blockType().solid());
}
}
@@ -28,7 +28,7 @@ public class SurfaceLocator implements Locator {
int min = Math.max(search.getMin(), column.getMinY());
if(min >= max) return builder.build();
for(int y = min; y < max; y++) {
if(column.getBlock(y).isAir() && !column.getBlock(y - 1).isAir()) {
if(column.getBlock(y).air() && !column.getBlock(y - 1).air()) {
builder.set(y);
}
}
@@ -23,7 +23,7 @@ public class TopLocator implements Locator {
@Override
public BinaryColumn getSuitableCoordinates(Column<?> column) {
for(int y = search.getMax(); y >= search.getMin(); y--) {
if(column.getBlock(y).isAir() && !column.getBlock(y - 1).isAir()) {
if(column.getBlock(y).air() && !column.getBlock(y - 1).air()) {
return new BinaryColumn(y, y + 1, yi -> true);
}
}
@@ -149,7 +149,7 @@ public class VanillaOre implements Structure {
if(!visited.get(index)) { // Skip blocks that have already been visited
visited.set(index);
BlockType block = world.getBlockState(xi, yi, zi).getBlockType();
BlockType block = world.getBlockState(xi, yi, zi).blockType();
if(shouldPlace(getReplaceable(), block, exposed, random, world, xi, yi, zi)) {
world.setBlockState(xi, yi, zi, getMaterial(block), isApplyGravity());
++blockCount;
@@ -31,7 +31,7 @@ public class VanillaScatteredOre extends VanillaOre {
for(int j = 0; j < i; ++j) {
this.setPos(mutable, random, location, Math.min(j, spread));
BlockType block = world.getBlockState(mutable).getBlockType();
BlockType block = world.getBlockState(mutable).blockType();
if(shouldPlace(getReplaceable(), block, exposed, random, world, mutable.getX(), mutable.getY(), mutable.getZ())) {
world.setBlockState(mutable, getMaterial(block), isApplyGravity());
}
@@ -21,12 +21,12 @@ public class VanillaOreUtils {
if(!replaceable.contains(type)) return false;
if(shouldExpose(random, exposedChance)) return true; // Exposed blocks can be placed regardless of adjacency to air
// Adjacency is checked after determining not exposed rather than vice-versa, assuming block checks are more expensive
boolean adjacentAir = world.getBlockState(x, y, z - 1).isAir() ||
world.getBlockState(x, y, z + 1).isAir() ||
world.getBlockState(x, y - 1, z).isAir() ||
world.getBlockState(x, y + 1, z).isAir() ||
world.getBlockState(x - 1, y, z).isAir() ||
world.getBlockState(x + 1, y, z).isAir();
boolean adjacentAir = world.getBlockState(x, y, z - 1).air() ||
world.getBlockState(x, y, z + 1).air() ||
world.getBlockState(x, y - 1, z).air() ||
world.getBlockState(x, y + 1, z).air() ||
world.getBlockState(x - 1, y, z).air() ||
world.getBlockState(x + 1, y, z).air();
return !adjacentAir; // Exposed check did not pass earlier so only blocks not adjacent air should place
}
}
@@ -66,12 +66,12 @@ public class ManifestAddon implements BaseAddon {
}
@Override
public Map<String, VersionRange> getDependencies() {
public Map<String, VersionRange> dependencies() {
return manifest.getDependencies();
}
@Override
public Version getVersion() {
public Version version() {
return manifest.getVersion();
}
}
@@ -132,7 +132,7 @@ public class ManifestAddonLoader implements BootstrapBaseAddon<ManifestAddon> {
}
@Override
public Version getVersion() {
public Version version() {
return VERSION;
}
}
@@ -4,7 +4,7 @@ contributors:
id: shortcut-blockstate-fallback
version: @VERSION@
entrypoints:
- "com.dfsek.terra.addons.shortcut.blockstate.ShortcutBlockstateFallbackAddon"
- "com.dfsek.terra.addons.shortcut.blockstate.ShortcutBlockStateFallbackAddon"
website:
issues: https://github.com/PolyhedralDev/Terra/issues
source: https://github.com/PolyhedralDev/Terra
@@ -76,7 +76,7 @@ public class BlockFunction implements Function<Void> {
y.apply(implementationArguments, scope).doubleValue(),
FloatingPointFunctions.round(xz.getZ())).mutable().add(arguments.getOrigin().toFloat());
BlockState current = arguments.getWorld().getBlockState(set);
if(overwrite.apply(implementationArguments, scope) || current.isAir()) {
if(overwrite.apply(implementationArguments, scope) || current.air()) {
arguments.getWorld().setBlockState(set, rot, physics.apply(implementationArguments, scope));
}
} catch(RuntimeException e) {
@@ -45,7 +45,7 @@ public class CheckBlockFunction implements Function<String> {
.add(Vector3.of(FloatingPointFunctions.round(xz.getX()),
y.apply(implementationArguments, scope)
.doubleValue(), FloatingPointFunctions.round(xz.getZ()))))
.getAsString();
.asString();
if(data.contains("[")) return data.substring(0, data.indexOf('[')); // Strip properties
else return data;
}
@@ -48,7 +48,7 @@ public class PullFunction implements Function<Void> {
Vector3.Mutable mutable = Vector3.of(FloatingPointFunctions.round(xz.getX()), y.apply(implementationArguments, scope).intValue(),
FloatingPointFunctions.round(xz.getZ())).mutable().add(arguments.getOrigin().toFloat());
while(mutable.getY() > arguments.getWorld().getMinHeight()) {
if(!arguments.getWorld().getBlockState(mutable).isAir()) {
if(!arguments.getWorld().getBlockState(mutable).air()) {
arguments.getWorld().setBlockState(mutable, data);
break;
}
@@ -31,7 +31,7 @@ public interface BaseAddon extends StringIdentifiable, Namespaced {
*
* @return Map of dependency ID to {@link VersionRange} of dependency
*/
default Map<String, VersionRange> getDependencies() {
default Map<String, VersionRange> dependencies() {
return Collections.emptyMap();
}
@@ -40,9 +40,9 @@ public interface BaseAddon extends StringIdentifiable, Namespaced {
*
* @return Version of addon
*/
Version getVersion();
Version version();
default String getNamespace() {
default String namespace() {
return getID();
}
}
@@ -20,19 +20,19 @@ public interface BlockType extends Handle {
*
* @return Default block state
*/
BlockState getDefaultState();
BlockState defaultState();
/**
* Get whether this block is solid.
*
* @return Whether this block is solid.
*/
boolean isSolid();
boolean solid();
/**
* Get whether this block is water.
*
* @return Whether this block is water.
*/
boolean isWater();
boolean water();
}
@@ -23,7 +23,7 @@ public interface BlockState extends Handle, Extendable {
/**
* Whether this {@link BlockState} matches another.
* <p>
* "matches" is defined as this {@link BlockState} holding a matching {@link #getBlockType()}.
* "matches" is defined as this {@link BlockState} holding a matching {@link #blockType()}.
*
* @param other Other {@link BlockState}
*
@@ -90,15 +90,15 @@ public interface BlockState extends Handle, Extendable {
*
* @return Block type.
*/
BlockType getBlockType();
BlockType blockType();
/**
* Get this state and its properties as a String
*
* @return String representation of this state
*/
default String getAsString() {
return getAsString(true);
default String asString() {
return asString(true);
}
/**
@@ -108,12 +108,12 @@ public interface BlockState extends Handle, Extendable {
*
* @return String representation of this state
*/
String getAsString(boolean properties);
String asString(boolean properties);
/**
* Get whether this BlockState is air
*
* @return Whether this state is air
*/
boolean isAir();
boolean air();
}
@@ -9,7 +9,7 @@ public interface BlockStateExtended extends BlockState {
*
* @return BlockData of this BlockStateExtended
*/
ExtendedData getData();
ExtendedData data();
/**
* Sets the BlockData.
@@ -25,8 +25,8 @@ public interface BlockStateExtended extends BlockState {
*
* @return Raw BlockState of this BlockStateExtended
*/
BlockState getState();
BlockState state();
@Override
default boolean isExtended() { return true; }
default boolean extended() { return true; }
}
@@ -16,7 +16,7 @@ import com.dfsek.terra.api.util.generic.data.types.Maybe;
public interface CommandSender extends Handle {
void sendMessage(String message);
Maybe<Entity> getEntity();
Maybe<Entity> entity();
Maybe<Player> getPlayer();
Maybe<Player> player();
}
@@ -1,7 +1,5 @@
package com.dfsek.terra.api.command.arguments;
import com.dfsek.terra.api.util.generic.data.types.Maybe;
import io.leangen.geantyref.TypeToken;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.incendo.cloud.component.CommandComponent;
@@ -14,7 +12,6 @@ import org.incendo.cloud.parser.ParserDescriptor;
import org.incendo.cloud.suggestion.Suggestion;
import org.incendo.cloud.suggestion.SuggestionProvider;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.function.Function;
import java.util.stream.Collectors;
@@ -103,15 +100,19 @@ public class RegistryArgument {
Registry<R> registry = registryFunction.apply(commandContext);
String finalInput = input;
return registry.get(RegistryKey.parse(input))
.map(ArgumentParseResult::success)
.orJust(() ->
registry.getByID(finalInput).collect(
left -> ArgumentParseResult.failure(new IllegalArgumentException(left)),
ArgumentParseResult::success
))
.get(() -> ArgumentParseResult.failure(new NoSuchEntryException("No such entry: " + finalInput)));
try {
return registry.get(RegistryKey.parse(input))
.map(ArgumentParseResult::success)
.orJust(() ->
registry.getByID(finalInput).collect(
left -> ArgumentParseResult.failure(new IllegalArgumentException(left)),
ArgumentParseResult::success
))
.get(() -> ArgumentParseResult.failure(new NoSuchEntryException("No such entry: " + finalInput)));
} catch(IllegalArgumentException e) {
return ArgumentParseResult.failure(e);
}
}
@Override
@@ -7,5 +7,5 @@ public interface Extendable {
*
* @return Whether this state is extended.
*/
default boolean isExtended() { return false; }
default boolean extended() { return false; }
}
@@ -28,5 +28,5 @@ public interface EntityTypeExtended extends EntityType {
EntityType getType();
@Override
default boolean isExtended() { return true; }
default boolean extended() { return true; }
}
@@ -0,0 +1,12 @@
package com.dfsek.terra.api.error;
import com.dfsek.terra.api.util.generic.data.types.Either;
public interface Invalid {
String message();
default <T> Either<Invalid, T> left() {
return Either.left(this);
}
}
@@ -0,0 +1,8 @@
package com.dfsek.terra.api.error;
public record InvalidBlockStateError(Exception exception) implements Invalid {
@Override
public String message() {
return exception.getMessage();
}
}
@@ -7,6 +7,9 @@
package com.dfsek.terra.api.handle;
import com.dfsek.terra.api.error.Invalid;
import com.dfsek.terra.api.util.generic.data.types.Either;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
@@ -20,7 +23,7 @@ import com.dfsek.terra.api.entity.EntityType;
public interface WorldHandle {
@NotNull
@Contract("_ -> new")
BlockState createBlockState(@NotNull String data);
Either<Invalid, BlockState> createBlockState(@NotNull String data);
@NotNull
@Contract(pure = true)
@@ -5,8 +5,8 @@ public interface Keyed<T extends Keyed<T>> extends Namespaced, StringIdentifiabl
RegistryKey getRegistryKey();
@Override
default String getNamespace() {
return getRegistryKey().getNamespace();
default String namespace() {
return getRegistryKey().namespace();
}
@Override
@@ -1,9 +1,9 @@
package com.dfsek.terra.api.registry.key;
public interface Namespaced {
String getNamespace();
String namespace();
default RegistryKey key(String id) {
return RegistryKey.of(getNamespace(), id);
return RegistryKey.of(namespace(), id);
}
}
@@ -41,7 +41,7 @@ public final class RegistryKey implements StringIdentifiable, Namespaced {
}
@Override
public String getNamespace() {
public String namespace() {
return namespace;
}
@@ -46,7 +46,7 @@ public class BlockStateSet extends HashSet<BlockType> {
}
private void add(BlockState data) {
add(data.getBlockType());
add(data.blockType());
}
private static final class Singleton extends BlockStateSet {
@@ -49,10 +49,10 @@ public interface Maybe<T> extends Monad<T, Maybe<?>> {
return this;
}
default <T1> Maybe<T1> overwrite(Maybe<T1> m) {
return bind(ignore -> m);
}
/**
* Project a new value into this Maybe if it is Nothing.
*/
Maybe<T> or(Supplier<Maybe<T>> or);
default Maybe<T> orJust(Supplier<T> or) {
@@ -274,7 +274,7 @@ public abstract class AbstractPlatform implements Platform {
.append("- ")
.append(addon.getID())
.append("@")
.append(addon.getVersion().getFormatted());
.append(addon.version().getFormatted());
}
logger.info(builder.toString());
@@ -41,13 +41,13 @@ public class DependencySorter {
}
private void sortDependencies(BaseAddon addon, List<BaseAddon> sort) {
addon.getDependencies().forEach((id, range) -> {
addon.dependencies().forEach((id, range) -> {
BaseAddon dependency = get(id, addon);
if(!range.isSatisfiedBy(dependency.getVersion())) {
if(!range.isSatisfiedBy(dependency.version())) {
throw new DependencyVersionException(
"Addon " + addon.getID() + " specifies dependency on " + id + ", versions " + range.getFormatted() +
", but non-matching version " + dependency.getVersion().getFormatted() + " is installed.");
", but non-matching version " + dependency.version().getFormatted() + " is installed.");
}
if(!visited.get(dependency.getID())) { // if we've not visited it yet
@@ -63,14 +63,14 @@ public class DependencySorter {
private BaseAddon get(String id, BaseAddon addon) {
if(!addons.containsKey(id)) {
throw new DependencyException("Addon " + addon.getID() + " specifies dependency on " + id + ", versions " +
addon.getDependencies().get(id).getFormatted() +
addon.dependencies().get(id).getFormatted() +
", but no such addon is installed.");
}
return addons.get(id);
}
private void checkDependencies(BaseAddon base, BaseAddon current) {
current.getDependencies().forEach((id, range) -> {
current.dependencies().forEach((id, range) -> {
BaseAddon dependency = get(id, current);
if(dependency.getID().equals(base.getID())) {
throw new CircularDependencyException(
@@ -15,7 +15,7 @@ public class EphemeralAddon implements BaseAddon {
}
@Override
public Version getVersion() {
public Version version() {
return version;
}
@@ -36,7 +36,7 @@ public class InternalAddon implements BaseAddon {
}
@Override
public Version getVersion() {
public Version version() {
return VERSION;
}
}
@@ -61,7 +61,7 @@ public class GenericLoaders implements LoaderRegistrar {
if(platform != null) {
registry.registerLoader(BaseAddon.class, platform.getAddons())
.registerLoader(BlockType.class, (type, object, configLoader, depthTracker) -> platform
.getWorldHandle().createBlockState((String) object).getBlockType())
.getWorldHandle().createBlockState((String) object).blockType())
.registerLoader(BlockState.class, (type, object, configLoader, depthTracker) -> platform
.getWorldHandle().createBlockState((String) object));
}
@@ -59,7 +59,7 @@ public class FunctionalEventHandlerImpl implements FunctionalEventHandler {
throw e; // Rethrow if it's fail-through.
// else warn
logger.warn("Exception occurred during event handling. Report this to the maintainers of {}@{}",
context.getAddon().getID(), context.getAddon().getVersion().getFormatted(), e);
context.getAddon().getID(), context.getAddon().version().getFormatted(), e);
}
});
}
@@ -63,7 +63,7 @@ public class BootstrapAddonLoader implements BootstrapBaseAddon<BootstrapBaseAdd
}
logger.debug("Loaded bootstrap addon {}@{} with entry point {}",
addon.getID(), addon.getVersion().getFormatted(), addonObject.getClass());
addon.getID(), addon.version().getFormatted(), addonObject.getClass());
return addon;
} catch(InvocationTargetException e) {
throw new AddonLoadException("Exception occurred while instantiating addon", e);
@@ -103,7 +103,7 @@ public class BootstrapAddonLoader implements BootstrapBaseAddon<BootstrapBaseAdd
}
@Override
public Version getVersion() {
public Version version() {
return VERSION;
}
}