From 59d5a6469ca37e8958427cf25aae832d5a74674c Mon Sep 17 00:00:00 2001 From: RednedEpic Date: Sun, 1 May 2022 12:25:24 -0500 Subject: [PATCH] Add support for modifying identifiers through the AvailableEntityIdentifiersPacket This is the first of many commits that address adding support for custom entities through the Geyser API. --- .../org/geysermc/geyser/api/GeyserApi.java | 8 ++ .../geysermc/geyser/api/command/Command.java | 55 ++++++++++- .../geyser/api/command/CommandManager.java | 9 -- .../geyser/api/entity/EntityIdentifier.java | 97 +++++++++++++++++++ .../api/event/entity/DefineEntitiesEvent.java | 46 +++++++++ .../geyser/api/provider/BuilderProvider.java | 47 +++++++++ .../geyser/api/provider/Provider.java | 29 ++++++ .../geyser/api/provider/ProviderManager.java | 41 ++++++++ .../java/org/geysermc/geyser/GeyserImpl.java | 7 ++ .../geyser/command/GeyserCommandManager.java | 5 - .../geyser/entity/GeyserEntityIdentifier.java | 85 ++++++++++++++++ .../geyser/registry/ProviderRegistries.java | 42 ++++++++ .../loader/ProviderRegistryLoader.java | 45 +++++++++ .../registry/provider/AbstractProvider.java | 39 ++++++++ .../provider/GeyserBuilderProvider.java | 64 ++++++++++++ .../provider/GeyserProviderManager.java | 36 +++++++ .../registry/provider/ProviderSupplier.java | 31 ++++++ .../geyser/session/GeyserSession.java | 34 ++++++- 18 files changed, 702 insertions(+), 18 deletions(-) create mode 100644 api/geyser/src/main/java/org/geysermc/geyser/api/entity/EntityIdentifier.java create mode 100644 api/geyser/src/main/java/org/geysermc/geyser/api/event/entity/DefineEntitiesEvent.java create mode 100644 api/geyser/src/main/java/org/geysermc/geyser/api/provider/BuilderProvider.java create mode 100644 api/geyser/src/main/java/org/geysermc/geyser/api/provider/Provider.java create mode 100644 api/geyser/src/main/java/org/geysermc/geyser/api/provider/ProviderManager.java create mode 100644 core/src/main/java/org/geysermc/geyser/entity/GeyserEntityIdentifier.java create mode 100644 core/src/main/java/org/geysermc/geyser/registry/ProviderRegistries.java create mode 100644 core/src/main/java/org/geysermc/geyser/registry/loader/ProviderRegistryLoader.java create mode 100644 core/src/main/java/org/geysermc/geyser/registry/provider/AbstractProvider.java create mode 100644 core/src/main/java/org/geysermc/geyser/registry/provider/GeyserBuilderProvider.java create mode 100644 core/src/main/java/org/geysermc/geyser/registry/provider/GeyserProviderManager.java create mode 100644 core/src/main/java/org/geysermc/geyser/registry/provider/ProviderSupplier.java diff --git a/api/geyser/src/main/java/org/geysermc/geyser/api/GeyserApi.java b/api/geyser/src/main/java/org/geysermc/geyser/api/GeyserApi.java index 4366e9ed6..96c23d267 100644 --- a/api/geyser/src/main/java/org/geysermc/geyser/api/GeyserApi.java +++ b/api/geyser/src/main/java/org/geysermc/geyser/api/GeyserApi.java @@ -35,6 +35,7 @@ import org.geysermc.geyser.api.event.EventBus; import org.geysermc.geyser.api.extension.ExtensionManager; import org.geysermc.geyser.api.network.BedrockListener; import org.geysermc.geyser.api.network.RemoteServer; +import org.geysermc.geyser.api.provider.ProviderManager; import java.util.List; import java.util.UUID; @@ -99,6 +100,13 @@ public interface GeyserApi extends GeyserApiBase { */ CommandManager commandManager(); + /** + * Gets the {@link ProviderManager}. + * + * @return the provider manager + */ + ProviderManager providerManager(); + /** * Gets the {@link EventBus} for handling * Geyser events. diff --git a/api/geyser/src/main/java/org/geysermc/geyser/api/command/Command.java b/api/geyser/src/main/java/org/geysermc/geyser/api/command/Command.java index 2c48473c6..55e894dd7 100644 --- a/api/geyser/src/main/java/org/geysermc/geyser/api/command/Command.java +++ b/api/geyser/src/main/java/org/geysermc/geyser/api/command/Command.java @@ -98,27 +98,80 @@ public interface Command { } static Command.Builder builder(Class sourceType) { - return GeyserApi.api().commandManager().provideBuilder(sourceType); + return GeyserApi.api().providerManager().builderProvider().provideBuilder(Builder.class, sourceType); } interface Builder { + /** + * Sets the command name. + * + * @param name the command name + * @return the builder + */ Builder name(String name); + /** + * Sets the command description. + * + * @param description the command description + * @return the builder + */ Builder description(String description); + /** + * Sets the permission node. + * + * @param permission the permission node + * @return the builder + */ Builder permission(String permission); + /** + * Sets the aliases. + * + * @param aliases the aliases + * @return the builder + */ Builder aliases(List aliases); + /** + * Sets if this command is executable on console. + * + * @param executableOnConsole if this command is executable on console + * @return the builder + */ Builder executableOnConsole(boolean executableOnConsole); + /** + * Sets the subcommands. + * + * @param subCommands the subcommands + * @return the builder + */ Builder subCommands(List subCommands); + /** + * Sets if this command is bedrock only. + * + * @param bedrockOnly if this command is bedrock only + * @return the builder + */ Builder bedrockOnly(boolean bedrockOnly); + /** + * Sets the {@link CommandExecutor} for this command. + * + * @param executor the command executor + * @return the builder + */ Builder executor(CommandExecutor executor); + /** + * Builds the command. + * + * @return the command + */ Command build(); } } diff --git a/api/geyser/src/main/java/org/geysermc/geyser/api/command/CommandManager.java b/api/geyser/src/main/java/org/geysermc/geyser/api/command/CommandManager.java index 864ba71a4..9f29651ba 100644 --- a/api/geyser/src/main/java/org/geysermc/geyser/api/command/CommandManager.java +++ b/api/geyser/src/main/java/org/geysermc/geyser/api/command/CommandManager.java @@ -34,15 +34,6 @@ import java.util.Map; */ public abstract class CommandManager { - /** - * Provides a {@link Command.Builder}. - * - * @param sourceType the command source type - * @param the type - * @return a command builder - */ - protected abstract Command.Builder provideBuilder(Class sourceType); - /** * Registers the given {@link Command}. * diff --git a/api/geyser/src/main/java/org/geysermc/geyser/api/entity/EntityIdentifier.java b/api/geyser/src/main/java/org/geysermc/geyser/api/entity/EntityIdentifier.java new file mode 100644 index 000000000..1c82d3a63 --- /dev/null +++ b/api/geyser/src/main/java/org/geysermc/geyser/api/entity/EntityIdentifier.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2019-2022 GeyserMC. http://geysermc.org + * + * 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. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.geyser.api.entity; + +import org.checkerframework.checker.nullness.qual.NonNull; +import org.geysermc.geyser.api.GeyserApi; + +/** + * Represents the data sent over to a client regarding + * an entity's identifier. + */ +public interface EntityIdentifier { + + /** + * Gets whether this entity has a spawn egg or not. + * + * @return whether this entity has a spawn egg or not + */ + boolean hasSpawnEgg(); + + /** + * Gets the entity's identifier that is sent to the client. + * + * @return the entity's identifier that is sent to the client. + */ + @NonNull + String identifier(); + + /** + * Gets whether the entity is summonable or not. + * + * @return whether the entity is summonable or not + */ + boolean isSummonable(); + + @NonNull + static Builder builder() { + return GeyserApi.api().providerManager().builderProvider().provideBuilder(Builder.class); + } + + interface Builder { + + /** + * Sets whether the entity has a spawn egg or not. + * + * @param spawnEgg whether the entity has a spawn egg or not + * @return the builder + */ + Builder spawnEgg(boolean spawnEgg); + + /** + * Sets the entity's identifier that is sent to the client. + * + * @param identifier the entity's identifier that is sent to the client + * @return the builder + */ + Builder identifier(String identifier); + + /** + * Sets whether the entity is summonable or not. + * + * @param summonable whether the entity is summonable or not + * @return the builder + */ + Builder summonable(boolean summonable); + + /** + * Builds the entity identifier. + * + * @return the entity identifier + */ + EntityIdentifier build(); + } +} diff --git a/api/geyser/src/main/java/org/geysermc/geyser/api/event/entity/DefineEntitiesEvent.java b/api/geyser/src/main/java/org/geysermc/geyser/api/event/entity/DefineEntitiesEvent.java new file mode 100644 index 000000000..9bdae3dba --- /dev/null +++ b/api/geyser/src/main/java/org/geysermc/geyser/api/event/entity/DefineEntitiesEvent.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2019-2022 GeyserMC. http://geysermc.org + * + * 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. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.geyser.api.event.entity; + +import org.checkerframework.checker.nullness.qual.NonNull; +import org.geysermc.geyser.api.connection.GeyserConnection; +import org.geysermc.geyser.api.entity.EntityIdentifier; +import org.geysermc.geyser.api.event.Event; + +import java.util.List; + +/** + * Called when Geyser sends a list of available entities to the + * Bedrock client. This will typically contain all the available + * entities within vanilla, but can be modified to include any custom + * entity defined through a resource pack. + * + * @param connection the {@link GeyserConnection} that is receiving the entities + * @param identifiers a mutable list of all the {@link EntityIdentifier}s + * sent to the client + */ +public record DefineEntitiesEvent(@NonNull GeyserConnection connection, @NonNull List identifiers) implements Event { +} diff --git a/api/geyser/src/main/java/org/geysermc/geyser/api/provider/BuilderProvider.java b/api/geyser/src/main/java/org/geysermc/geyser/api/provider/BuilderProvider.java new file mode 100644 index 000000000..b05a36f88 --- /dev/null +++ b/api/geyser/src/main/java/org/geysermc/geyser/api/provider/BuilderProvider.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2019-2022 GeyserMC. http://geysermc.org + * + * 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. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.geyser.api.provider; + +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; + +/** + * Allows for obtaining instances of a builder that are + * used for constructing various data. + */ +public interface BuilderProvider extends Provider { + + /** + * Provides a builder for the specified builder type. + * + * @param builderClass the builder class + * @param the resulting type + * @param the builder type + * @return the builder instance + */ + @NonNull + B provideBuilder(@NonNull Class builderClass, @Nullable Object... args); +} diff --git a/api/geyser/src/main/java/org/geysermc/geyser/api/provider/Provider.java b/api/geyser/src/main/java/org/geysermc/geyser/api/provider/Provider.java new file mode 100644 index 000000000..4463efeed --- /dev/null +++ b/api/geyser/src/main/java/org/geysermc/geyser/api/provider/Provider.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2019-2022 GeyserMC. http://geysermc.org + * + * 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. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.geyser.api.provider; + +public interface Provider { +} diff --git a/api/geyser/src/main/java/org/geysermc/geyser/api/provider/ProviderManager.java b/api/geyser/src/main/java/org/geysermc/geyser/api/provider/ProviderManager.java new file mode 100644 index 000000000..48ec99a3f --- /dev/null +++ b/api/geyser/src/main/java/org/geysermc/geyser/api/provider/ProviderManager.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2019-2022 GeyserMC. http://geysermc.org + * + * 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. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.geyser.api.provider; + +/** + * Holds a record of every {@link Provider} available + * that allows for accessing various information throughout + * the API. + */ +public interface ProviderManager { + + /** + * Returns the {@link BuilderProvider}. + * + * @return the builder provider + */ + BuilderProvider builderProvider(); +} diff --git a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java index 38d567bde..188393f4c 100644 --- a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java +++ b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java @@ -70,6 +70,7 @@ import org.geysermc.geyser.network.RemoteServerImpl; import org.geysermc.geyser.pack.ResourcePack; import org.geysermc.geyser.registry.BlockRegistries; import org.geysermc.geyser.registry.Registries; +import org.geysermc.geyser.registry.provider.GeyserProviderManager; import org.geysermc.geyser.scoreboard.ScoreboardUpdater; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.PendingMicrosoftAuthentication; @@ -145,6 +146,7 @@ public class GeyserImpl implements GeyserApi { private final EventBus eventBus; private final GeyserExtensionManager extensionManager; + private final GeyserProviderManager providerManager = new GeyserProviderManager(); private final RemoteServer remoteServer; private final BedrockListener bedrockListener; @@ -576,6 +578,11 @@ public class GeyserImpl implements GeyserApi { return this.bootstrap.getGeyserCommandManager(); } + @Override + public GeyserProviderManager providerManager() { + return this.providerManager; + } + @Override public EventBus eventBus() { return this.eventBus; diff --git a/core/src/main/java/org/geysermc/geyser/command/GeyserCommandManager.java b/core/src/main/java/org/geysermc/geyser/command/GeyserCommandManager.java index 0214a44fd..c242106d8 100644 --- a/core/src/main/java/org/geysermc/geyser/command/GeyserCommandManager.java +++ b/core/src/main/java/org/geysermc/geyser/command/GeyserCommandManager.java @@ -148,11 +148,6 @@ public abstract class GeyserCommandManager extends CommandManager { */ public abstract String description(String command); - @Override - protected Command.Builder provideBuilder(Class sourceType) { - return new CommandBuilder<>(sourceType); - } - @RequiredArgsConstructor public static class CommandBuilder implements Command.Builder { private final Class sourceType; diff --git a/core/src/main/java/org/geysermc/geyser/entity/GeyserEntityIdentifier.java b/core/src/main/java/org/geysermc/geyser/entity/GeyserEntityIdentifier.java new file mode 100644 index 000000000..9a4a5e5d5 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/entity/GeyserEntityIdentifier.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2019-2022 GeyserMC. http://geysermc.org + * + * 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. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.geyser.entity; + +import com.nukkitx.nbt.NbtMap; +import com.nukkitx.nbt.NbtMapBuilder; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.geysermc.geyser.api.entity.EntityIdentifier; + +import java.util.concurrent.atomic.AtomicInteger; + +public record GeyserEntityIdentifier(NbtMap nbt) implements EntityIdentifier { + private static final AtomicInteger RUNTIME_ID_ALLOCATORS = new AtomicInteger(100000); + + @Override + public boolean hasSpawnEgg() { + return this.nbt.getBoolean("hasspawnegg"); + } + + @NonNull + @Override + public String identifier() { + return this.nbt.getString("id"); + } + + @Override + public boolean isSummonable() { + return this.nbt.getBoolean("summonable"); + } + + public static class EntityIdentifierBuilder implements EntityIdentifier.Builder { + private final NbtMapBuilder nbt = NbtMap.builder(); + + @Override + public Builder spawnEgg(boolean spawnEgg) { + this.nbt.putBoolean("hasspawnegg", spawnEgg); + return this; + } + + @Override + public Builder identifier(String identifier) { + this.nbt.putString("id", identifier); + return this; + } + + @Override + public Builder summonable(boolean summonable) { + this.nbt.putBoolean("summonable", summonable); + return this; + } + + @Override + public EntityIdentifier build() { + // Vanilla registry information + this.nbt.putString("bid", ""); + this.nbt.putInt("rid", RUNTIME_ID_ALLOCATORS.getAndIncrement()); + this.nbt.putBoolean("experimental", false); + + return new GeyserEntityIdentifier(this.nbt.build()); + } + } +} diff --git a/core/src/main/java/org/geysermc/geyser/registry/ProviderRegistries.java b/core/src/main/java/org/geysermc/geyser/registry/ProviderRegistries.java new file mode 100644 index 000000000..46b44c8da --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/registry/ProviderRegistries.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2019-2022 GeyserMC. http://geysermc.org + * + * 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. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.geyser.registry; + +import org.geysermc.geyser.api.provider.Provider; +import org.geysermc.geyser.registry.loader.ProviderRegistryLoader; +import org.geysermc.geyser.registry.provider.GeyserBuilderProvider; +import org.geysermc.geyser.registry.provider.ProviderSupplier; + +/** + * Holds registries for the available {@link Provider}s + */ +public class ProviderRegistries { + + /** + * A registry containing all the providers for builders. + */ + public static final SimpleMappedRegistry, ProviderSupplier> BUILDERS = SimpleMappedRegistry.create(GeyserBuilderProvider.INSTANCE, ProviderRegistryLoader::new); +} diff --git a/core/src/main/java/org/geysermc/geyser/registry/loader/ProviderRegistryLoader.java b/core/src/main/java/org/geysermc/geyser/registry/loader/ProviderRegistryLoader.java new file mode 100644 index 000000000..290f2991b --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/registry/loader/ProviderRegistryLoader.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2019-2022 GeyserMC. http://geysermc.org + * + * 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. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.geyser.registry.loader; + +import org.geysermc.geyser.registry.provider.AbstractProvider; +import org.geysermc.geyser.registry.provider.ProviderSupplier; + +import java.util.IdentityHashMap; +import java.util.Map; + +/** + * Registers the provider data from the provider. + */ +public class ProviderRegistryLoader implements RegistryLoader, ProviderSupplier>> { + + @Override + public Map, ProviderSupplier> load(AbstractProvider input) { + Map, ProviderSupplier> providers = new IdentityHashMap<>(); + input.registerProviders(providers); + return providers; + } +} diff --git a/core/src/main/java/org/geysermc/geyser/registry/provider/AbstractProvider.java b/core/src/main/java/org/geysermc/geyser/registry/provider/AbstractProvider.java new file mode 100644 index 000000000..8c5201c23 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/registry/provider/AbstractProvider.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2019-2022 GeyserMC. http://geysermc.org + * + * 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. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.geyser.registry.provider; + +import lombok.RequiredArgsConstructor; +import org.geysermc.geyser.api.provider.Provider; +import org.geysermc.geyser.registry.SimpleMappedRegistry; + +import java.util.Map; + +@RequiredArgsConstructor +public abstract class AbstractProvider implements Provider { + public abstract void registerProviders(Map, ProviderSupplier> providers); + + public abstract SimpleMappedRegistry, ProviderSupplier> providerRegistry(); +} diff --git a/core/src/main/java/org/geysermc/geyser/registry/provider/GeyserBuilderProvider.java b/core/src/main/java/org/geysermc/geyser/registry/provider/GeyserBuilderProvider.java new file mode 100644 index 000000000..57789ae55 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/registry/provider/GeyserBuilderProvider.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2019-2022 GeyserMC. http://geysermc.org + * + * 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. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.geyser.registry.provider; + +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.geysermc.geyser.api.command.Command; +import org.geysermc.geyser.api.command.CommandSource; +import org.geysermc.geyser.api.entity.EntityIdentifier; +import org.geysermc.geyser.api.provider.BuilderProvider; +import org.geysermc.geyser.command.GeyserCommandManager; +import org.geysermc.geyser.entity.GeyserEntityIdentifier; +import org.geysermc.geyser.registry.ProviderRegistries; +import org.geysermc.geyser.registry.SimpleMappedRegistry; + +import java.util.Map; + +public class GeyserBuilderProvider extends AbstractProvider implements BuilderProvider { + public static GeyserBuilderProvider INSTANCE = new GeyserBuilderProvider(); + + private GeyserBuilderProvider() { + } + + @SuppressWarnings("unchecked") + @Override + public void registerProviders(Map, ProviderSupplier> providers) { + providers.put(Command.Builder.class, args -> new GeyserCommandManager.CommandBuilder<>((Class) args[0])); + providers.put(EntityIdentifier.Builder.class, args -> new GeyserEntityIdentifier.EntityIdentifierBuilder()); + } + + @Override + public SimpleMappedRegistry, ProviderSupplier> providerRegistry() { + return ProviderRegistries.BUILDERS; + } + + @SuppressWarnings("unchecked") + @Override + public @NonNull B provideBuilder(@NonNull Class builderClass, @Nullable Object... args) { + return (B) this.providerRegistry().get(builderClass).create(args); + } +} diff --git a/core/src/main/java/org/geysermc/geyser/registry/provider/GeyserProviderManager.java b/core/src/main/java/org/geysermc/geyser/registry/provider/GeyserProviderManager.java new file mode 100644 index 000000000..208981d7a --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/registry/provider/GeyserProviderManager.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2019-2022 GeyserMC. http://geysermc.org + * + * 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. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.geyser.registry.provider; + +import org.geysermc.geyser.api.provider.ProviderManager; + +public class GeyserProviderManager implements ProviderManager { + + @Override + public GeyserBuilderProvider builderProvider() { + return GeyserBuilderProvider.INSTANCE; + } +} diff --git a/core/src/main/java/org/geysermc/geyser/registry/provider/ProviderSupplier.java b/core/src/main/java/org/geysermc/geyser/registry/provider/ProviderSupplier.java new file mode 100644 index 000000000..6cb220ce4 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/registry/provider/ProviderSupplier.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2019-2022 GeyserMC. http://geysermc.org + * + * 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. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.geyser.registry.provider; + +public interface ProviderSupplier { + + Object create(Object... args); +} diff --git a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java index a4508f0b5..8e8bbd8fc 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -61,6 +61,9 @@ import com.github.steveice10.packetlib.tcp.TcpClientSession; import com.github.steveice10.packetlib.tcp.TcpSession; import com.nukkitx.math.GenericMath; import com.nukkitx.math.vector.*; +import com.nukkitx.nbt.NbtMap; +import com.nukkitx.nbt.NbtMapBuilder; +import com.nukkitx.nbt.NbtType; import com.nukkitx.protocol.bedrock.BedrockPacket; import com.nukkitx.protocol.bedrock.BedrockServerSession; import com.nukkitx.protocol.bedrock.data.*; @@ -88,9 +91,12 @@ import org.geysermc.floodgate.util.BedrockData; import org.geysermc.geyser.Constants; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.api.connection.GeyserConnection; +import org.geysermc.geyser.api.entity.EntityIdentifier; +import org.geysermc.geyser.api.event.entity.DefineEntitiesEvent; import org.geysermc.geyser.api.network.RemoteServer; import org.geysermc.geyser.command.GeyserCommandSource; import org.geysermc.geyser.configuration.EmoteOffhandWorkaroundOption; +import org.geysermc.geyser.entity.GeyserEntityIdentifier; import org.geysermc.geyser.entity.attribute.GeyserAttributeType; import org.geysermc.geyser.entity.type.Entity; import org.geysermc.geyser.entity.type.ItemFrameEntity; @@ -129,6 +135,7 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.Collectors; @Getter public class GeyserSession implements GeyserConnection, GeyserCommandSource { @@ -595,9 +602,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { biomeDefinitionListPacket.setDefinitions(Registries.BIOMES_NBT.get()); upstream.sendPacket(biomeDefinitionListPacket); - AvailableEntityIdentifiersPacket entityPacket = new AvailableEntityIdentifiersPacket(); - entityPacket.setIdentifiers(Registries.BEDROCK_ENTITY_IDENTIFIERS.get()); - upstream.sendPacket(entityPacket); + this.sendAvailableEntityIdentifiers(); CreativeContentPacket creativePacket = new CreativeContentPacket(); creativePacket.setContents(this.itemMappings.getCreativeItems()); @@ -627,6 +632,29 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { upstream.sendPacket(gamerulePacket); } + public void sendAvailableEntityIdentifiers() { + NbtMap nbt = Registries.BEDROCK_ENTITY_IDENTIFIERS.get(); + List idlist = nbt.getList("idlist", NbtType.COMPOUND); + List identifiers = new ArrayList<>(idlist.size()); + for (NbtMap identifier : idlist) { + identifiers.add(new GeyserEntityIdentifier(identifier)); + } + + DefineEntitiesEvent event = new DefineEntitiesEvent(this, identifiers); + this.geyser.eventBus().fire(event); + + NbtMapBuilder builder = nbt.toBuilder(); + builder.putList("idlist", NbtType.COMPOUND, event.identifiers() + .stream() + .map(identifer -> ((GeyserEntityIdentifier) identifer).nbt()) + .collect(Collectors.toList()) + ); + + AvailableEntityIdentifiersPacket entityPacket = new AvailableEntityIdentifiersPacket(); + entityPacket.setIdentifiers(builder.build()); + upstream.sendPacket(entityPacket); + } + public void authenticate(String username) { authenticate(username, ""); }