From ae8534d1784f9d07bb1f4a65d7945f55f0d73a49 Mon Sep 17 00:00:00 2001 From: MrHell228 Date: Mon, 21 Apr 2025 03:55:20 +0300 Subject: [PATCH 1/3] add SignalAwareVolume --- .../api/registry/RegistryTypes.java | 3 + .../spongepowered/api/world/SignalType.java | 36 ++ .../spongepowered/api/world/SignalTypes.java | 74 ++++ .../api/world/volume/game/Region.java | 1 + .../world/volume/game/SignalAwareVolume.java | 322 ++++++++++++++++++ 5 files changed, 436 insertions(+) create mode 100644 src/main/java/org/spongepowered/api/world/SignalType.java create mode 100644 src/main/java/org/spongepowered/api/world/SignalTypes.java create mode 100644 src/main/java/org/spongepowered/api/world/volume/game/SignalAwareVolume.java diff --git a/src/main/java/org/spongepowered/api/registry/RegistryTypes.java b/src/main/java/org/spongepowered/api/registry/RegistryTypes.java index 4f2155b98c..c42aad9a4f 100644 --- a/src/main/java/org/spongepowered/api/registry/RegistryTypes.java +++ b/src/main/java/org/spongepowered/api/registry/RegistryTypes.java @@ -161,6 +161,7 @@ import org.spongepowered.api.world.ChunkRegenerateFlag; import org.spongepowered.api.world.HeightType; import org.spongepowered.api.world.LightType; +import org.spongepowered.api.world.SignalType; import org.spongepowered.api.world.WorldType; import org.spongepowered.api.world.biome.Biome; import org.spongepowered.api.world.biome.climate.GrassColorModifier; @@ -491,6 +492,8 @@ public final class RegistryTypes { public static final DefaultedRegistryType SELECTOR_TYPE = RegistryTypes.spongeKeyInGame("selector_type"); + public static final DefaultedRegistryType SIGNAL_TYPE = RegistryTypes.spongeKeyInGame("signal_type"); + public static final DefaultedRegistryType SKIN_PART = RegistryTypes.spongeKeyInGame("skin_part"); public static final DefaultedRegistryType SLAB_PORTION = RegistryTypes.spongeKeyInGame("slab_portion"); diff --git a/src/main/java/org/spongepowered/api/world/SignalType.java b/src/main/java/org/spongepowered/api/world/SignalType.java new file mode 100644 index 0000000000..05310dce0e --- /dev/null +++ b/src/main/java/org/spongepowered/api/world/SignalType.java @@ -0,0 +1,36 @@ +/* + * This file is part of SpongeAPI, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.api.world; + +import org.spongepowered.api.registry.DefaultedRegistryValue; +import org.spongepowered.api.util.annotation.CatalogedBy; +import org.spongepowered.api.world.volume.game.SignalAwareVolume; + +/** + * Represents a type of the signal in the {@link SignalAwareVolume}. + */ +@CatalogedBy(SignalTypes.class) +public interface SignalType extends DefaultedRegistryValue { +} diff --git a/src/main/java/org/spongepowered/api/world/SignalTypes.java b/src/main/java/org/spongepowered/api/world/SignalTypes.java new file mode 100644 index 0000000000..6683309574 --- /dev/null +++ b/src/main/java/org/spongepowered/api/world/SignalTypes.java @@ -0,0 +1,74 @@ +/* + * This file is part of SpongeAPI, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.api.world; + +import org.spongepowered.api.ResourceKey; +import org.spongepowered.api.Sponge; +import org.spongepowered.api.block.BlockTypes; +import org.spongepowered.api.registry.DefaultedRegistryReference; +import org.spongepowered.api.registry.Registry; +import org.spongepowered.api.registry.RegistryKey; +import org.spongepowered.api.registry.RegistryScope; +import org.spongepowered.api.registry.RegistryScopes; +import org.spongepowered.api.registry.RegistryTypes; +import org.spongepowered.api.world.volume.game.SignalAwareVolume; + +@RegistryScopes(scopes = RegistryScope.GAME) +public final class SignalTypes { + + /** + * Powers neighbours. + */ + public static final DefaultedRegistryReference WEAK = SignalTypes.key(ResourceKey.sponge("weak")); + + /** + * Powers neighbours and goes through them powering their neighbours. + */ + public static final DefaultedRegistryReference STRONG = SignalTypes.key(ResourceKey.sponge("strong")); + + /** + * The combination of {@link #WEAK} and {@link #STRONG} signals.
+ * Usually depends on block properties to choose between these two signals + * (e.g. if the block {@link SignalAwareVolume#canConductSignal(int, int, int)}). + */ + public static final DefaultedRegistryReference COMPOSITE = SignalTypes.key(ResourceKey.sponge("composite")); + + /** + * Doesn't directly power anything but can be extracted + * by some blocks (e.g. {@link BlockTypes#COMPARATOR}). + */ + public static final DefaultedRegistryReference ANALOG = SignalTypes.key(ResourceKey.sponge("analog")); + + private SignalTypes() { + } + + public static Registry registry() { + return Sponge.game().registry(RegistryTypes.SIGNAL_TYPE); + } + + private static DefaultedRegistryReference key(final ResourceKey location) { + return RegistryKey.of(RegistryTypes.SIGNAL_TYPE, location).asDefaultedReference(Sponge::game); + } +} diff --git a/src/main/java/org/spongepowered/api/world/volume/game/Region.java b/src/main/java/org/spongepowered/api/world/volume/game/Region.java index a5ce3e28c0..dc9aeec9ac 100644 --- a/src/main/java/org/spongepowered/api/world/volume/game/Region.java +++ b/src/main/java/org/spongepowered/api/world/volume/game/Region.java @@ -40,6 +40,7 @@ public interface Region> extends EnvironmentalVolume, + SignalAwareVolume, BiomeVolume.Streamable, BlockVolume.Streamable, BlockEntityVolume.Streamable, diff --git a/src/main/java/org/spongepowered/api/world/volume/game/SignalAwareVolume.java b/src/main/java/org/spongepowered/api/world/volume/game/SignalAwareVolume.java new file mode 100644 index 0000000000..94cc8b3cd5 --- /dev/null +++ b/src/main/java/org/spongepowered/api/world/volume/game/SignalAwareVolume.java @@ -0,0 +1,322 @@ +/* + * This file is part of SpongeAPI, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.api.world.volume.game; + +import org.spongepowered.api.util.Direction; +import org.spongepowered.api.world.SignalType; +import org.spongepowered.math.vector.Vector3i; + +import java.util.Objects; +import java.util.function.Supplier; + +/** + * A volume aware of the signal that can "power" blocks.
+ * This signal is often referred to as "redstone signal". + */ +public interface SignalAwareVolume extends PrimitiveGameVolume { + + /** + * Returns whether the given position can conduct the signal. + * + * @param x The x position + * @param y The y position + * @param z The z position + * @return True if the given position can conduct the signal + */ + boolean canConductSignal(int x, int y, int z); + + /** + * Returns whether the given position can conduct the signal. + * + * @param position The position + * @return True if the given position can conduct the signal + */ + default boolean canConductSignal(final Vector3i position) { + Objects.requireNonNull(position, "position"); + return this.canConductSignal(position.x(), position.y(), position.z()); + } + + /** + * Returns whether the given position can emit the signal of the given type. + * + * @param type The signal type + * @param x The x position + * @param y The y position + * @param z The z position + * @return True if the given position can emit the signal of the given type + */ + boolean canEmitSignal(SignalType type, int x, int y, int z); + + /** + * Returns whether the given position can emit the signal of the given type. + * + * @param type The signal type + * @param x The x position + * @param y The y position + * @param z The z position + * @return True if the given position can emit the signal of the given type + */ + default boolean canEmitSignal(final Supplier type, final int x, final int y, final int z) { + Objects.requireNonNull(type, "type"); + return this.canEmitSignal(type.get(), x, y, z); + } + + /** + * Returns whether the given position can emit the signal of the given type. + * + * @param type The signal type + * @param position The position + * @return True if the given position can emit the signal of the given type + */ + default boolean canEmitSignal(final SignalType type, final Vector3i position) { + Objects.requireNonNull(position, "position"); + return this.canEmitSignal(type, position.x(), position.y(), position.z()); + } + + /** + * Returns whether the given position can emit the signal of the given type. + * + * @param type The signal type + * @param position The position + * @return True if the given position can emit the signal of the given type + */ + default boolean canEmitSignal(final Supplier type, final Vector3i position) { + Objects.requireNonNull(type, "type"); + Objects.requireNonNull(position, "position"); + return this.canEmitSignal(type.get(), position.x(), position.y(), position.z()); + } + + /** + * Returns the signal of the given type emitted from the given position in the given direction. + * + * @param type The signal type + * @param x The x position + * @param y The y position + * @param z The z position + * @param direction The direction + * @return The signal of the given type emitted from the given position in the given direction + */ + int signalFrom(SignalType type, int x, int y, int z, Direction direction); + + /** + * Returns the signal of the given type emitted from the given position in the given direction. + * + * @param type The signal type + * @param x The x position + * @param y The y position + * @param z The z position + * @param direction The direction + * @return The signal of the given type emitted from the given position in the given direction + */ + default int signalFrom(final Supplier type, final int x, final int y, final int z, final Direction direction) { + Objects.requireNonNull(type, "type"); + return this.signalFrom(type.get(), x, y, z, direction); + } + + /** + * Returns the signal of the given type emitted from the given position in the given direction. + * + * @param type The signal type + * @param position The position + * @param direction The direction + * @return The signal of the given type emitted from the given position in the given direction + */ + default int signalFrom(final SignalType type, final Vector3i position, final Direction direction) { + Objects.requireNonNull(position, "position"); + return this.signalFrom(type, position.x(), position.y(), position.z(), direction); + } + + /** + * Returns the signal of the given type emitted from the given position in the given direction. + * + * @param type The signal type + * @param position The position + * @param direction The direction + * @return The signal of the given type emitted from the given position in the given direction + */ + default int signalFrom(final Supplier type, final Vector3i position, final Direction direction) { + Objects.requireNonNull(type, "type"); + Objects.requireNonNull(position, "position"); + return this.signalFrom(type.get(), position.x(), position.y(), position.z(), direction); + } + + /** + * Returns whether there is signal of the given type emitted from the given position in the given direction. + * + * @param type The signal type + * @param x The x position + * @param y The y position + * @param z The z position + * @param direction The direction + * @return True if there is signal of the given type emitted from the given position in the given direction + */ + default boolean hasSignalFrom(final SignalType type, final int x, final int y, final int z, final Direction direction) { + return this.signalFrom(type, x, y, z, direction) > 0; + } + + /** + * Returns whether there is signal of the given type emitted from the given position in the given direction. + * + * @param type The signal type + * @param x The x position + * @param y The y position + * @param z The z position + * @param direction The direction + * @return True if there is signal of the given type emitted from the given position in the given direction + */ + default boolean hasSignalFrom(final Supplier type, final int x, final int y, final int z, final Direction direction) { + Objects.requireNonNull(type, "type"); + return this.hasSignalFrom(type.get(), x, y, z, direction); + } + + /** + * Returns whether there is signal of the given type emitted from the given position in the given direction. + * + * @param type The signal type + * @param position The position + * @param direction The direction + * @return True if there is signal of the given type emitted from the given position in the given direction + */ + default boolean hasSignalFrom(final SignalType type, final Vector3i position, final Direction direction) { + Objects.requireNonNull(position, "position"); + return this.hasSignalFrom(type, position.x(), position.y(), position.z(), direction); + } + + /** + * Returns whether there is signal of the given type emitted from the given position in the given direction. + * + * @param type The signal type + * @param position The position + * @param direction The direction + * @return True if there is signal of the given type emitted from the given position in the given direction + */ + default boolean hasSignalFrom(final Supplier type, final Vector3i position, final Direction direction) { + Objects.requireNonNull(type, "type"); + Objects.requireNonNull(position, "position"); + return this.hasSignalFrom(type.get(), position.x(), position.y(), position.z(), direction); + } + + /** + * Returns the highest signal of the given type emitted towards the given position from its neighbours. + * + * @param type The signal type + * @param x The x position + * @param y The y position + * @param z The z position + * @return The highest signal of the given type emitted towards the given position from its neighbours + */ + int highestSignalAt(SignalType type, int x, int y, int z); + + /** + * Returns the highest signal of the given type emitted towards the given position from its neighbours. + * + * @param type The signal type + * @param x The x position + * @param y The y position + * @param z The z position + * @return The highest signal of the given type emitted towards the given position from its neighbours + */ + default int highestSignalAt(final Supplier type, final int x, final int y, final int z) { + Objects.requireNonNull(type, "type"); + return this.highestSignalAt(type.get(), x, y, z); + } + + /** + * Returns the highest signal of the given type emitted towards the given position from its neighbours. + * + * @param type The signal type + * @param position The position + * @return The highest signal of the given type emitted towards the given position from its neighbours + */ + default int highestSignalAt(final SignalType type, final Vector3i position) { + Objects.requireNonNull(position, "position"); + return this.highestSignalAt(type, position.x(), position.y(), position.z()); + } + + /** + * Returns the highest signal of the given type emitted towards the given position from its neighbours. + * + * @param type The signal type + * @param position The position + * @return The highest signal of the given type emitted towards the given position from its neighbours + */ + default int highestSignalAt(final Supplier type, final Vector3i position) { + Objects.requireNonNull(type, "type"); + Objects.requireNonNull(position, "position"); + return this.highestSignalAt(type.get(), position.x(), position.y(), position.z()); + } + + /** + * Returns whether there is any signal of the given type emitted towards the given position from its neighbours. + * + * @param type The signal type + * @param x The x position + * @param y The y position + * @param z The z position + * @return True if there is any signal of the given type emitted towards the given position from its neighbours + */ + default boolean hasSignalAt(final SignalType type, final int x, final int y, final int z) { + return this.highestSignalAt(type, x, y, z) > 0; + } + + /** + * Returns whether there is any signal of the given type emitted towards the given position from its neighbours. + * + * @param type The signal type + * @param x The x position + * @param y The y position + * @param z The z position + * @return True if there is any signal of the given type emitted towards the given position from its neighbours + */ + default boolean hasSignalAt(final Supplier type, final int x, final int y, final int z) { + Objects.requireNonNull(type, "type"); + return this.hasSignalAt(type.get(), x, y, z); + } + + /** + * Returns whether there is any signal of the given type emitted towards the given position from its neighbours. + * + * @param type The signal type + * @param position The position + * @return True if there is any signal of the given type emitted towards the given position from its neighbours + */ + default boolean hasSignalAt(final SignalType type, final Vector3i position) { + Objects.requireNonNull(position, "position"); + return this.hasSignalAt(type, position.x(), position.y(), position.z()); + } + + /** + * Returns whether there is any signal of the given type emitted towards the given position from its neighbours. + * + * @param type The signal type + * @param position The position + * @return True if there is any signal of the given type emitted towards the given position from its neighbours + */ + default boolean hasSignalAt(final Supplier type, final Vector3i position) { + Objects.requireNonNull(type, "type"); + Objects.requireNonNull(position, "position"); + return this.hasSignalAt(type.get(), position.x(), position.y(), position.z()); + } +} From 26abaff679d7a90f94c24511dd52cf1e687ee032 Mon Sep 17 00:00:00 2001 From: MrHell228 Date: Wed, 23 Apr 2025 02:45:03 +0300 Subject: [PATCH 2/3] Update SignalTypes.java --- src/main/java/org/spongepowered/api/world/SignalTypes.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/spongepowered/api/world/SignalTypes.java b/src/main/java/org/spongepowered/api/world/SignalTypes.java index 6683309574..222f7a2976 100644 --- a/src/main/java/org/spongepowered/api/world/SignalTypes.java +++ b/src/main/java/org/spongepowered/api/world/SignalTypes.java @@ -44,7 +44,7 @@ public final class SignalTypes { public static final DefaultedRegistryReference WEAK = SignalTypes.key(ResourceKey.sponge("weak")); /** - * Powers neighbours and goes through them powering their neighbours. + * Goes through neighbours powering their neighbours. */ public static final DefaultedRegistryReference STRONG = SignalTypes.key(ResourceKey.sponge("strong")); From 81f4a330a02ee3a0f708cda80fc87bf3913f9ab5 Mon Sep 17 00:00:00 2001 From: MrHell228 Date: Mon, 9 Jun 2025 18:51:42 +0300 Subject: [PATCH 3/3] rename SignalTypes WEAK & STRONG -> DIRECT & INDIRECT --- src/main/java/org/spongepowered/api/world/SignalTypes.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/spongepowered/api/world/SignalTypes.java b/src/main/java/org/spongepowered/api/world/SignalTypes.java index 222f7a2976..2b1185f331 100644 --- a/src/main/java/org/spongepowered/api/world/SignalTypes.java +++ b/src/main/java/org/spongepowered/api/world/SignalTypes.java @@ -41,15 +41,15 @@ public final class SignalTypes { /** * Powers neighbours. */ - public static final DefaultedRegistryReference WEAK = SignalTypes.key(ResourceKey.sponge("weak")); + public static final DefaultedRegistryReference DIRECT = SignalTypes.key(ResourceKey.sponge("direct")); /** * Goes through neighbours powering their neighbours. */ - public static final DefaultedRegistryReference STRONG = SignalTypes.key(ResourceKey.sponge("strong")); + public static final DefaultedRegistryReference INDIRECT = SignalTypes.key(ResourceKey.sponge("indirect")); /** - * The combination of {@link #WEAK} and {@link #STRONG} signals.
+ * The combination of {@link #DIRECT} and {@link #INDIRECT} signals.
* Usually depends on block properties to choose between these two signals * (e.g. if the block {@link SignalAwareVolume#canConductSignal(int, int, int)}). */