+ * If no elements are specified, this will reset all currently hidden elements
+ *
+ * @param element the {@link GuiElement} to reset
+ */
+ void resetElement(@NonNull GuiElement @Nullable... element);
+
+ /**
+ * Determines whether a {@link GuiElement} is currently hidden.
+ *
+ * @param element the {@link GuiElement} to check
+ */
+ boolean isHudElementHidden(@NonNull GuiElement element);
+
+ /**
+ * Returns the currently hidden {@link GuiElement}s.
+ *
+ * @return an unmodifiable view of all currently hidden {@link GuiElement}s
+ */
+ @NonNull Set hiddenElements();
+}
diff --git a/api/src/main/java/org/geysermc/geyser/api/bedrock/camera/GuiElement.java b/api/src/main/java/org/geysermc/geyser/api/bedrock/camera/GuiElement.java
new file mode 100644
index 000000000..4d3653648
--- /dev/null
+++ b/api/src/main/java/org/geysermc/geyser/api/bedrock/camera/GuiElement.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2024 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.bedrock.camera;
+
+/**
+ * Represent GUI elements on the players HUD display.
+ * These can be hidden using {@link CameraData#hideElement(GuiElement...)},
+ * and one can reset their visibility using {@link CameraData#resetElement(GuiElement...)}.
+ */
+public class GuiElement {
+ public static final GuiElement PAPER_DOLL = new GuiElement(0);
+ public static final GuiElement ARMOR = new GuiElement(1);
+ public static final GuiElement TOOL_TIPS = new GuiElement(2);
+ public static final GuiElement TOUCH_CONTROLS = new GuiElement(3);
+ public static final GuiElement CROSSHAIR = new GuiElement(4);
+ public static final GuiElement HOTBAR = new GuiElement(5);
+ public static final GuiElement HEALTH = new GuiElement(6);
+ public static final GuiElement PROGRESS_BAR = new GuiElement(7);
+ public static final GuiElement FOOD_BAR = new GuiElement(8);
+ public static final GuiElement AIR_BUBBLES_BAR = new GuiElement(9);
+ public static final GuiElement VEHICLE_HEALTH = new GuiElement(10);
+ public static final GuiElement EFFECTS_BAR = new GuiElement(11);
+ public static final GuiElement ITEM_TEXT_POPUP = new GuiElement(12);
+
+ private GuiElement(int id) {
+ this.id = id;
+ }
+
+ private final int id;
+
+ /**
+ * Internal use only; don't depend on these values being consistent.
+ */
+ public int id() {
+ return this.id;
+ }
+}
diff --git a/api/src/main/java/org/geysermc/geyser/api/block/custom/nonvanilla/JavaBlockState.java b/api/src/main/java/org/geysermc/geyser/api/block/custom/nonvanilla/JavaBlockState.java
index f7da4b932..0dd0d3b33 100644
--- a/api/src/main/java/org/geysermc/geyser/api/block/custom/nonvanilla/JavaBlockState.java
+++ b/api/src/main/java/org/geysermc/geyser/api/block/custom/nonvanilla/JavaBlockState.java
@@ -73,7 +73,10 @@ public interface JavaBlockState {
* Gets whether the block state has block entity
*
* @return whether the block state has block entity
+ * @deprecated Does not have an effect. If you were using this to
+ * set piston behavior, use {@link #pistonBehavior()} instead.
*/
+ @Deprecated(forRemoval = true)
boolean hasBlockEntity();
/**
@@ -104,6 +107,11 @@ public interface JavaBlockState {
Builder pistonBehavior(@Nullable String pistonBehavior);
+ /**
+ * @deprecated Does not have an effect. If you were using this to
+ * * set piston behavior, use {@link #pistonBehavior(String)} instead.
+ */
+ @Deprecated(forRemoval = true)
Builder hasBlockEntity(boolean hasBlockEntity);
JavaBlockState build();
diff --git a/api/src/main/java/org/geysermc/geyser/api/event/bedrock/SessionLoginEvent.java b/api/src/main/java/org/geysermc/geyser/api/event/bedrock/SessionLoginEvent.java
index 522562d11..86a5ec6f8 100644
--- a/api/src/main/java/org/geysermc/geyser/api/event/bedrock/SessionLoginEvent.java
+++ b/api/src/main/java/org/geysermc/geyser/api/event/bedrock/SessionLoginEvent.java
@@ -36,7 +36,7 @@ import java.util.Map;
import java.util.Objects;
/**
- * Called when a session has logged in, and is about to connect to a remote java server.
+ * Called when a session has logged in, and is about to connect to a remote Java server.
* This event is cancellable, and can be used to prevent the player from connecting to the remote server.
*/
public final class SessionLoginEvent extends ConnectionEvent implements Cancellable {
@@ -99,9 +99,9 @@ public final class SessionLoginEvent extends ConnectionEvent implements Cancella
}
/**
- * Gets the {@link RemoteServer} the section will attempt to connect to.
+ * Gets the {@link RemoteServer} the session will attempt to connect to.
*
- * @return the {@link RemoteServer} the section will attempt to connect to.
+ * @return the {@link RemoteServer} the session will attempt to connect to.
*/
public @NonNull RemoteServer remoteServer() {
return this.remoteServer;
diff --git a/api/src/main/java/org/geysermc/geyser/api/event/bedrock/SessionSkinApplyEvent.java b/api/src/main/java/org/geysermc/geyser/api/event/bedrock/SessionSkinApplyEvent.java
new file mode 100644
index 000000000..f22241e41
--- /dev/null
+++ b/api/src/main/java/org/geysermc/geyser/api/event/bedrock/SessionSkinApplyEvent.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2019-2024 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.bedrock;
+
+import org.checkerframework.checker.nullness.qual.NonNull;
+import org.geysermc.geyser.api.connection.GeyserConnection;
+import org.geysermc.geyser.api.event.connection.ConnectionEvent;
+import org.geysermc.geyser.api.skin.Cape;
+import org.geysermc.geyser.api.skin.Skin;
+import org.geysermc.geyser.api.skin.SkinData;
+import org.geysermc.geyser.api.skin.SkinGeometry;
+
+import java.util.UUID;
+
+/**
+ * Called when a skin is applied to a player.
+ *
+ * Won't be called when a fake player is spawned for a player skull.
+ */
+public abstract class SessionSkinApplyEvent extends ConnectionEvent {
+
+ private final String username;
+ private final UUID uuid;
+ private final boolean slim;
+ private final boolean bedrock;
+ private final SkinData originalSkinData;
+
+ public SessionSkinApplyEvent(@NonNull GeyserConnection connection, String username, UUID uuid, boolean slim, boolean bedrock, SkinData skinData) {
+ super(connection);
+ this.username = username;
+ this.uuid = uuid;
+ this.slim = slim;
+ this.bedrock = bedrock;
+ this.originalSkinData = skinData;
+ }
+
+ /**
+ * The username of the player.
+ *
+ * @return the username of the player
+ */
+ public @NonNull String username() {
+ return username;
+ }
+
+ /**
+ * The UUID of the player.
+ *
+ * @return the UUID of the player
+ */
+ public @NonNull UUID uuid() {
+ return uuid;
+ }
+
+ /**
+ * If the player is using a slim model.
+ *
+ * @return if the player is using a slim model
+ */
+ public boolean slim() {
+ return slim;
+ }
+
+ /**
+ * If the player is a Bedrock player.
+ *
+ * @return if the player is a Bedrock player
+ */
+ public boolean bedrock() {
+ return bedrock;
+ }
+
+ /**
+ * The original skin data of the player.
+ *
+ * @return the original skin data of the player
+ */
+ public @NonNull SkinData originalSkin() {
+ return originalSkinData;
+ }
+
+ /**
+ * The skin data of the player.
+ *
+ * @return the current skin data of the player
+ */
+ public abstract @NonNull SkinData skinData();
+
+ /**
+ * Change the skin of the player.
+ *
+ * @param newSkin the new skin
+ */
+ public abstract void skin(@NonNull Skin newSkin);
+
+ /**
+ * Change the cape of the player.
+ *
+ * @param newCape the new cape
+ */
+ public abstract void cape(@NonNull Cape newCape);
+
+ /**
+ * Change the geometry of the player.
+ *
+ * @param newGeometry the new geometry
+ */
+ public abstract void geometry(@NonNull SkinGeometry newGeometry);
+
+ /**
+ * Change the geometry of the player.
+ *
+ * Constructs a generic {@link SkinGeometry} object with the given data.
+ *
+ * @param geometryName the name of the geometry
+ * @param geometryData the data of the geometry
+ */
+ public void geometry(@NonNull String geometryName, @NonNull String geometryData) {
+ geometry(new SkinGeometry("{\"geometry\" :{\"default\" :\"" + geometryName + "\"}}", geometryData));
+ }
+}
diff --git a/api/src/main/java/org/geysermc/geyser/api/event/connection/ConnectionRequestEvent.java b/api/src/main/java/org/geysermc/geyser/api/event/connection/ConnectionRequestEvent.java
index 5c1f4ef51..b36ee8bfb 100644
--- a/api/src/main/java/org/geysermc/geyser/api/event/connection/ConnectionRequestEvent.java
+++ b/api/src/main/java/org/geysermc/geyser/api/event/connection/ConnectionRequestEvent.java
@@ -46,13 +46,35 @@ public final class ConnectionRequestEvent implements Event, Cancellable {
this.proxyIp = proxyIp;
}
+ /**
+ * The IP address of the client attempting to connect
+ *
+ * @return the IP address of the client attempting to connect
+ * @deprecated Use {@link #inetSocketAddress()} instead
+ */
+ @NonNull @Deprecated(forRemoval = true)
+ public InetSocketAddress getInetSocketAddress() {
+ return ip;
+ }
+
+ /**
+ * The IP address of the proxy handling the connection. It will return null if there is no proxy.
+ *
+ * @return the IP address of the proxy handling the connection
+ * @deprecated Use {@link #proxyIp()} instead
+ */
+ @Nullable @Deprecated(forRemoval = true)
+ public InetSocketAddress getProxyIp() {
+ return proxyIp;
+ }
+
/**
* The IP address of the client attempting to connect
*
* @return the IP address of the client attempting to connect
*/
@NonNull
- public InetSocketAddress getInetSocketAddress() {
+ public InetSocketAddress inetSocketAddress() {
return ip;
}
@@ -62,7 +84,7 @@ public final class ConnectionRequestEvent implements Event, Cancellable {
* @return the IP address of the proxy handling the connection
*/
@Nullable
- public InetSocketAddress getProxyIp() {
+ public InetSocketAddress proxyIp() {
return proxyIp;
}
diff --git a/core/src/main/java/org/geysermc/geyser/util/collection/package-info.java b/api/src/main/java/org/geysermc/geyser/api/skin/Cape.java
similarity index 66%
rename from core/src/main/java/org/geysermc/geyser/util/collection/package-info.java
rename to api/src/main/java/org/geysermc/geyser/api/skin/Cape.java
index 46fa5df11..1e7341ae4 100644
--- a/core/src/main/java/org/geysermc/geyser/util/collection/package-info.java
+++ b/api/src/main/java/org/geysermc/geyser/api/skin/Cape.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
+ * Copyright (c) 2024 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
@@ -23,12 +23,18 @@
* @link https://github.com/GeyserMC/Geyser
*/
+package org.geysermc.geyser.api.skin;
+
/**
- * Contains useful collections for use in Geyser.
- *
- * Of note are the fixed int maps. Designed for use with block states that are positive and sequential, they do not allow keys to be
- * added that are not greater by one versus the previous key. Because of this, speedy operations of {@link java.util.Map#get(java.lang.Object)}
- * and {@link java.util.Map#containsKey(java.lang.Object)} can be performed by simply checking the bounds of the map
- * size and its "start" integer.
+ * Represents a cape.
+ *
+ * @param textureUrl The URL of the cape texture
+ * @param capeId The ID of the cape
+ * @param capeData The raw cape image data in ARGB format
+ * @param failed If the cape failed to load, this is for things like fallback capes
*/
-package org.geysermc.geyser.util.collection;
\ No newline at end of file
+public record Cape(String textureUrl, String capeId, byte[] capeData, boolean failed) {
+ public Cape(String textureUrl, String capeId, byte[] capeData) {
+ this(textureUrl, capeId, capeData, false);
+ }
+}
diff --git a/api/src/main/java/org/geysermc/geyser/api/skin/Skin.java b/api/src/main/java/org/geysermc/geyser/api/skin/Skin.java
new file mode 100644
index 000000000..9b39ddfe8
--- /dev/null
+++ b/api/src/main/java/org/geysermc/geyser/api/skin/Skin.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2024 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.skin;
+
+/**
+ * Represents a skin.
+ *
+ * @param textureUrl The URL/ID of the skin texture
+ * @param skinData The raw skin image data in ARGB
+ * @param failed If the skin failed to load, this is for things like fallback skins
+ */
+public record Skin(String textureUrl, byte[] skinData, boolean failed) {
+ public Skin(String textureUrl, byte[] skinData) {
+ this(textureUrl, skinData, false);
+ }
+}
diff --git a/api/src/main/java/org/geysermc/geyser/api/skin/SkinData.java b/api/src/main/java/org/geysermc/geyser/api/skin/SkinData.java
new file mode 100644
index 000000000..9de4a3534
--- /dev/null
+++ b/api/src/main/java/org/geysermc/geyser/api/skin/SkinData.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2024 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.skin;
+
+/**
+ * Represents a full package of {@link Skin}, {@link Cape}, and {@link SkinGeometry}.
+ */
+public record SkinData(Skin skin, Cape cape, SkinGeometry geometry) {
+}
diff --git a/api/src/main/java/org/geysermc/geyser/api/skin/SkinGeometry.java b/api/src/main/java/org/geysermc/geyser/api/skin/SkinGeometry.java
new file mode 100644
index 000000000..5b40d2022
--- /dev/null
+++ b/api/src/main/java/org/geysermc/geyser/api/skin/SkinGeometry.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2024 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.skin;
+
+/**
+ * Represents geometry of a skin.
+ *
+ * @param geometryName The name of the geometry (JSON)
+ * @param geometryData The geometry data (JSON)
+ */
+public record SkinGeometry(String geometryName, String geometryData) {
+
+ public static SkinGeometry WIDE = getLegacy(false);
+ public static SkinGeometry SLIM = getLegacy(true);
+
+ /**
+ * Generate generic geometry
+ *
+ * @param isSlim if true, it will be the slimmer alex model
+ * @return The generic geometry object
+ */
+ private static SkinGeometry getLegacy(boolean isSlim) {
+ return new SkinGeometry("{\"geometry\" :{\"default\" :\"geometry.humanoid.custom" + (isSlim ? "Slim" : "") + "\"}}", "");
+ }
+}
diff --git a/bootstrap/bungeecord/build.gradle.kts b/bootstrap/bungeecord/build.gradle.kts
index e93c096a1..910e50723 100644
--- a/bootstrap/bungeecord/build.gradle.kts
+++ b/bootstrap/bungeecord/build.gradle.kts
@@ -34,3 +34,8 @@ tasks.withType {
exclude(dependency("io.netty:netty-resolver-dns:.*"))
}
}
+
+modrinth {
+ uploadFile.set(tasks.getByPath("shadowJar"))
+ loaders.add("bungeecord")
+}
diff --git a/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeeLogger.java b/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeeLogger.java
index daeb20102..e8cf7ee39 100644
--- a/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeeLogger.java
+++ b/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeeLogger.java
@@ -26,22 +26,19 @@
package org.geysermc.geyser.platform.bungeecord;
import lombok.Getter;
+import lombok.RequiredArgsConstructor;
import lombok.Setter;
import org.geysermc.geyser.GeyserLogger;
import java.util.logging.Level;
import java.util.logging.Logger;
+@RequiredArgsConstructor
public class GeyserBungeeLogger implements GeyserLogger {
private final Logger logger;
@Getter @Setter
private boolean debug;
- public GeyserBungeeLogger(Logger logger, boolean debug) {
- this.logger = logger;
- this.debug = debug;
- }
-
@Override
public void severe(String message) {
logger.severe(message);
diff --git a/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeePlugin.java b/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeePlugin.java
index 4191c8578..cd6b59f64 100644
--- a/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeePlugin.java
+++ b/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeePlugin.java
@@ -58,14 +58,13 @@ import java.util.Map;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
-import java.util.logging.Level;
public class GeyserBungeePlugin extends Plugin implements GeyserBootstrap {
private GeyserCommandManager geyserCommandManager;
private GeyserBungeeConfiguration geyserConfig;
private GeyserBungeeInjector geyserInjector;
- private GeyserBungeeLogger geyserLogger;
+ private final GeyserBungeeLogger geyserLogger = new GeyserBungeeLogger(getLogger());
private IGeyserPingPassthrough geyserBungeePingPassthrough;
private GeyserImpl geyser;
@@ -82,21 +81,21 @@ public class GeyserBungeePlugin extends Plugin implements GeyserBootstrap {
// Copied from ViaVersion.
// https://github.com/ViaVersion/ViaVersion/blob/b8072aad86695cc8ec6f5e4103e43baf3abf6cc5/bungee/src/main/java/us/myles/ViaVersion/BungeePlugin.java#L43
try {
- ProtocolConstants.class.getField("MINECRAFT_1_20_3");
+ ProtocolConstants.class.getField("MINECRAFT_1_21");
} catch (NoSuchFieldException e) {
- getLogger().warning(" / \\");
- getLogger().warning(" / \\");
- getLogger().warning(" / | \\");
- getLogger().warning(" / | \\ " + GeyserLocale.getLocaleStringLog("geyser.bootstrap.unsupported_proxy", getProxy().getName()));
- getLogger().warning(" / \\ " + GeyserLocale.getLocaleStringLog("geyser.may_not_work_as_intended_all_caps"));
- getLogger().warning(" / o \\");
- getLogger().warning("/_____________\\");
+ geyserLogger.error(" / \\");
+ geyserLogger.error(" / \\");
+ geyserLogger.error(" / | \\");
+ geyserLogger.error(" / | \\ " + GeyserLocale.getLocaleStringLog("geyser.bootstrap.unsupported_proxy", getProxy().getName()));
+ geyserLogger.error(" / \\ " + GeyserLocale.getLocaleStringLog("geyser.may_not_work_as_intended_all_caps"));
+ geyserLogger.error(" / o \\");
+ geyserLogger.error("/_____________\\");
}
if (!this.loadConfig()) {
return;
}
- this.geyserLogger = new GeyserBungeeLogger(getLogger(), geyserConfig.isDebugMode());
+ this.geyserLogger.setDebug(geyserConfig.isDebugMode());
GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger);
this.geyser = GeyserImpl.load(PlatformType.BUNGEECORD, this);
this.geyserInjector = new GeyserBungeeInjector(this);
@@ -293,7 +292,7 @@ public class GeyserBungeePlugin extends Plugin implements GeyserBootstrap {
"config.yml", (x) -> x.replaceAll("generateduuid", UUID.randomUUID().toString()), this);
this.geyserConfig = FileUtils.loadConfig(configFile, GeyserBungeeConfiguration.class);
} catch (IOException ex) {
- getLogger().log(Level.SEVERE, GeyserLocale.getLocaleStringLog("geyser.config.failed"), ex);
+ geyserLogger.error(GeyserLocale.getLocaleStringLog("geyser.config.failed"), ex);
ex.printStackTrace();
return false;
}
diff --git a/bootstrap/mod/build.gradle.kts b/bootstrap/mod/build.gradle.kts
index 7651a2df2..32224d00b 100644
--- a/bootstrap/mod/build.gradle.kts
+++ b/bootstrap/mod/build.gradle.kts
@@ -6,6 +6,13 @@ loom {
mixin.defaultRefmapName.set("geyser-refmap.json")
}
+afterEvaluate {
+ // We don't need these
+ tasks.named("remapModrinthJar").configure {
+ enabled = false
+ }
+}
+
dependencies {
api(projects.core)
compileOnly(libs.mixin)
diff --git a/bootstrap/mod/fabric/build.gradle.kts b/bootstrap/mod/fabric/build.gradle.kts
index cd513c1e4..25bd0af9d 100644
--- a/bootstrap/mod/fabric/build.gradle.kts
+++ b/bootstrap/mod/fabric/build.gradle.kts
@@ -63,6 +63,7 @@ tasks {
modrinth {
loaders.add("fabric")
+ uploadFile.set(tasks.getByPath("remapModrinthJar"))
dependencies {
required.project("fabric-api")
}
diff --git a/bootstrap/mod/fabric/src/main/resources/fabric.mod.json b/bootstrap/mod/fabric/src/main/resources/fabric.mod.json
index 93f48b73c..262f9833a 100644
--- a/bootstrap/mod/fabric/src/main/resources/fabric.mod.json
+++ b/bootstrap/mod/fabric/src/main/resources/fabric.mod.json
@@ -23,8 +23,8 @@
"geyser.mixins.json"
],
"depends": {
- "fabricloader": ">=0.15.10",
+ "fabricloader": ">=0.15.11",
"fabric": "*",
- "minecraft": ">=1.20.5"
+ "minecraft": ">=1.21"
}
}
diff --git a/bootstrap/mod/neoforge/build.gradle.kts b/bootstrap/mod/neoforge/build.gradle.kts
index ff77bcc5c..e0e7c2dfa 100644
--- a/bootstrap/mod/neoforge/build.gradle.kts
+++ b/bootstrap/mod/neoforge/build.gradle.kts
@@ -31,7 +31,9 @@ dependencies {
// Let's shade in our own api
shadow(projects.api) { isTransitive = false }
- shadow(projects.common) { isTransitive = false }
+
+ // cannot be shaded, since neoforge will complain if floodgate-neoforge tries to provide this
+ include(projects.common)
// Include all transitive deps of core via JiJ
includeTransitive(projects.core)
@@ -53,4 +55,5 @@ tasks {
modrinth {
loaders.add("neoforge")
+ uploadFile.set(tasks.getByPath("remapModrinthJar"))
}
\ No newline at end of file
diff --git a/bootstrap/mod/neoforge/src/main/java/org/geysermc/geyser/platform/neoforge/GeyserNeoForgeBootstrap.java b/bootstrap/mod/neoforge/src/main/java/org/geysermc/geyser/platform/neoforge/GeyserNeoForgeBootstrap.java
index 1655dea91..b97e42389 100644
--- a/bootstrap/mod/neoforge/src/main/java/org/geysermc/geyser/platform/neoforge/GeyserNeoForgeBootstrap.java
+++ b/bootstrap/mod/neoforge/src/main/java/org/geysermc/geyser/platform/neoforge/GeyserNeoForgeBootstrap.java
@@ -27,6 +27,7 @@ package org.geysermc.geyser.platform.neoforge;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.world.entity.player.Player;
+import net.neoforged.fml.ModContainer;
import net.neoforged.fml.common.Mod;
import net.neoforged.fml.loading.FMLLoader;
import net.neoforged.neoforge.common.NeoForge;
@@ -43,8 +44,8 @@ public class GeyserNeoForgeBootstrap extends GeyserModBootstrap {
private final GeyserNeoForgePermissionHandler permissionHandler = new GeyserNeoForgePermissionHandler();
- public GeyserNeoForgeBootstrap() {
- super(new GeyserNeoForgePlatform());
+ public GeyserNeoForgeBootstrap(ModContainer container) {
+ super(new GeyserNeoForgePlatform(container));
if (isServer()) {
// Set as an event so we can get the proper IP and port if needed
diff --git a/bootstrap/mod/neoforge/src/main/java/org/geysermc/geyser/platform/neoforge/GeyserNeoForgePlatform.java b/bootstrap/mod/neoforge/src/main/java/org/geysermc/geyser/platform/neoforge/GeyserNeoForgePlatform.java
index 63abe4a4a..41562baf3 100644
--- a/bootstrap/mod/neoforge/src/main/java/org/geysermc/geyser/platform/neoforge/GeyserNeoForgePlatform.java
+++ b/bootstrap/mod/neoforge/src/main/java/org/geysermc/geyser/platform/neoforge/GeyserNeoForgePlatform.java
@@ -26,20 +26,29 @@
package org.geysermc.geyser.platform.neoforge;
import net.minecraft.server.MinecraftServer;
+import net.neoforged.fml.ModContainer;
+import net.neoforged.fml.ModList;
import net.neoforged.fml.loading.FMLPaths;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
-import org.geysermc.geyser.GeyserBootstrap;
import org.geysermc.geyser.api.util.PlatformType;
import org.geysermc.geyser.dump.BootstrapDumpInfo;
import org.geysermc.geyser.platform.mod.GeyserModBootstrap;
import org.geysermc.geyser.platform.mod.platform.GeyserModPlatform;
+import java.io.IOException;
import java.io.InputStream;
+import java.nio.file.Files;
import java.nio.file.Path;
public class GeyserNeoForgePlatform implements GeyserModPlatform {
+ private final ModContainer container;
+
+ public GeyserNeoForgePlatform(ModContainer container) {
+ this.container = container;
+ }
+
@Override
public @NonNull PlatformType platformType() {
return PlatformType.NEOFORGE;
@@ -62,11 +71,21 @@ public class GeyserNeoForgePlatform implements GeyserModPlatform {
@Override
public boolean testFloodgatePluginPresent(@NonNull GeyserModBootstrap bootstrap) {
- return false; // No Floodgate mod for NeoForge yet
+ if (ModList.get().isLoaded("floodgate")) {
+ Path floodgateDataFolder = FMLPaths.CONFIGDIR.get().resolve("floodgate");
+ bootstrap.getGeyserConfig().loadFloodgate(bootstrap, floodgateDataFolder);
+ return true;
+ }
+ return false;
}
@Override
public @Nullable InputStream resolveResource(@NonNull String resource) {
- return GeyserBootstrap.class.getClassLoader().getResourceAsStream(resource);
+ try {
+ Path path = container.getModInfo().getOwningFile().getFile().findResource(resource);
+ return Files.newInputStream(path);
+ } catch (IOException e) {
+ return null;
+ }
}
}
diff --git a/bootstrap/mod/neoforge/src/main/resources/META-INF/neoforge.mods.toml b/bootstrap/mod/neoforge/src/main/resources/META-INF/neoforge.mods.toml
index ff2823aa2..fa01bb6ec 100644
--- a/bootstrap/mod/neoforge/src/main/resources/META-INF/neoforge.mods.toml
+++ b/bootstrap/mod/neoforge/src/main/resources/META-INF/neoforge.mods.toml
@@ -14,12 +14,12 @@ config = "geyser.mixins.json"
[[dependencies.geyser_neoforge]]
modId="neoforge"
type="required"
- versionRange="[20.5.0-beta,)"
+ versionRange="[21.0.0-beta,)"
ordering="NONE"
side="BOTH"
[[dependencies.geyser_neoforge]]
modId="minecraft"
type="required"
- versionRange="[1.20.5,1.21)"
+ versionRange="[1.21,)"
ordering="NONE"
side="BOTH"
\ No newline at end of file
diff --git a/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/GeyserModBootstrap.java b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/GeyserModBootstrap.java
index 786faac93..d7373f0a9 100644
--- a/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/GeyserModBootstrap.java
+++ b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/GeyserModBootstrap.java
@@ -34,7 +34,6 @@ import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.Commands;
import net.minecraft.server.MinecraftServer;
import net.minecraft.world.entity.player.Player;
-import org.apache.logging.log4j.LogManager;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.geysermc.geyser.GeyserBootstrap;
@@ -80,7 +79,7 @@ public abstract class GeyserModBootstrap implements GeyserBootstrap {
private GeyserCommandManager geyserCommandManager;
private GeyserModConfiguration geyserConfig;
private GeyserModInjector geyserInjector;
- private GeyserModLogger geyserLogger;
+ private final GeyserModLogger geyserLogger = new GeyserModLogger();
private IGeyserPingPassthrough geyserPingPassthrough;
private WorldManager geyserWorldManager;
@@ -92,7 +91,7 @@ public abstract class GeyserModBootstrap implements GeyserBootstrap {
if (!loadConfig()) {
return;
}
- this.geyserLogger = new GeyserModLogger(geyserConfig.isDebugMode());
+ this.geyserLogger.setDebug(geyserConfig.isDebugMode());
GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger);
this.geyser = GeyserImpl.load(this.platform.platformType(), this);
@@ -288,7 +287,7 @@ public abstract class GeyserModBootstrap implements GeyserBootstrap {
this.geyserConfig = FileUtils.loadConfig(configFile, GeyserModConfiguration.class);
return true;
} catch (IOException ex) {
- LogManager.getLogger("geyser").error(GeyserLocale.getLocaleStringLog("geyser.config.failed"), ex);
+ geyserLogger.error(GeyserLocale.getLocaleStringLog("geyser.config.failed"), ex);
ex.printStackTrace();
return false;
}
diff --git a/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/GeyserModLogger.java b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/GeyserModLogger.java
index 444b725e9..9260288d7 100644
--- a/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/GeyserModLogger.java
+++ b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/GeyserModLogger.java
@@ -37,10 +37,6 @@ public class GeyserModLogger implements GeyserLogger {
private boolean debug;
- public GeyserModLogger(boolean isDebug) {
- debug = isDebug;
- }
-
@Override
public void severe(String message) {
logger.fatal(message);
diff --git a/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/world/GeyserModWorldManager.java b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/world/GeyserModWorldManager.java
index 656305690..db1768737 100644
--- a/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/world/GeyserModWorldManager.java
+++ b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/world/GeyserModWorldManager.java
@@ -25,55 +25,45 @@
package org.geysermc.geyser.platform.mod.world;
-import org.geysermc.mcprotocollib.protocol.data.game.Holder;
-import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode;
-import org.geysermc.mcprotocollib.protocol.data.game.item.component.BannerPatternLayer;
-import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType;
-import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityInfo;
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
-import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import net.minecraft.SharedConstants;
import net.minecraft.core.BlockPos;
import net.minecraft.core.RegistryAccess;
import net.minecraft.core.component.DataComponents;
+import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.network.chat.Component;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerPlayer;
-import net.minecraft.server.network.Filterable;
import net.minecraft.world.item.ItemStack;
-import net.minecraft.world.item.component.WritableBookContent;
-import net.minecraft.world.item.component.WrittenBookContent;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BannerBlockEntity;
import net.minecraft.world.level.block.entity.BannerPatternLayers;
import net.minecraft.world.level.block.entity.BlockEntity;
-import net.minecraft.world.level.block.entity.LecternBlockEntity;
+import net.minecraft.world.level.block.entity.DecoratedPotBlockEntity;
import net.minecraft.world.level.chunk.ChunkAccess;
-import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.chunk.LevelChunkSection;
import net.minecraft.world.level.chunk.status.ChunkStatus;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.cloudburstmc.math.vector.Vector3i;
-import org.cloudburstmc.nbt.NbtMap;
-import org.cloudburstmc.nbt.NbtMapBuilder;
-import org.cloudburstmc.nbt.NbtType;
-import org.geysermc.erosion.util.LecternUtils;
import org.geysermc.geyser.level.GeyserWorldManager;
import org.geysermc.geyser.network.GameProtocol;
import org.geysermc.geyser.platform.mod.GeyserModBootstrap;
import org.geysermc.geyser.session.GeyserSession;
-import org.geysermc.geyser.util.BlockEntityUtils;
+import org.geysermc.geyser.util.MinecraftKey;
+import org.geysermc.mcprotocollib.protocol.data.game.Holder;
+import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode;
+import org.geysermc.mcprotocollib.protocol.data.game.item.component.BannerPatternLayer;
+import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType;
-import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.CompletableFuture;
+import java.util.function.Consumer;
public class GeyserModWorldManager extends GeyserWorldManager {
private static final GsonComponentSerializer GSON_SERIALIZER = GsonComponentSerializer.gson();
- private static final LegacyComponentSerializer LEGACY_SERIALIZER = LegacyComponentSerializer.legacySection();
private final MinecraftServer server;
public GeyserModWorldManager(MinecraftServer server) {
@@ -121,94 +111,6 @@ public class GeyserModWorldManager extends GeyserWorldManager {
return SharedConstants.getCurrentVersion().getProtocolVersion() == GameProtocol.getJavaProtocolVersion();
}
- @Override
- public boolean shouldExpectLecternHandled(GeyserSession session) {
- return true;
- }
-
- @Override
- public void sendLecternData(GeyserSession session, int x, int z, List blockEntityInfos) {
- server.execute(() -> {
- ServerPlayer player = getPlayer(session);
- if (player == null) {
- return;
- }
-
- //noinspection resource - level() is just a getter
- LevelChunk chunk = player.level().getChunk(x, z);
- final int chunkBlockX = x << 4;
- final int chunkBlockZ = z << 4;
- //noinspection ForLoopReplaceableByForEach - avoid constructing iterator
- for (int i = 0; i < blockEntityInfos.size(); i++) {
- BlockEntityInfo blockEntityInfo = blockEntityInfos.get(i);
- BlockEntity blockEntity = chunk.getBlockEntity(new BlockPos(chunkBlockX + blockEntityInfo.getX(),
- blockEntityInfo.getY(), chunkBlockZ + blockEntityInfo.getZ()));
- sendLecternData(session, blockEntity, true);
- }
- });
- }
-
- @Override
- public void sendLecternData(GeyserSession session, int x, int y, int z) {
- server.execute(() -> {
- ServerPlayer player = getPlayer(session);
- if (player == null) {
- return;
- }
- //noinspection resource - level() is just a getter
- BlockEntity blockEntity = player.level().getBlockEntity(new BlockPos(x, y, z));
- sendLecternData(session, blockEntity, false);
- });
- }
-
- private void sendLecternData(GeyserSession session, BlockEntity blockEntity, boolean isChunkLoad) {
- if (!(blockEntity instanceof LecternBlockEntity lectern)) {
- return;
- }
-
- int x = blockEntity.getBlockPos().getX();
- int y = blockEntity.getBlockPos().getY();
- int z = blockEntity.getBlockPos().getZ();
-
- if (!lectern.hasBook()) {
- if (!isChunkLoad) {
- BlockEntityUtils.updateBlockEntity(session, LecternUtils.getBaseLecternTag(x, y, z, 0).build(), Vector3i.from(x, y, z));
- }
- return;
- }
-
- ItemStack book = lectern.getBook();
- int pageCount = getPageCount(book);
- boolean hasBookPages = pageCount > 0;
- NbtMapBuilder lecternTag = LecternUtils.getBaseLecternTag(x, y, z, hasBookPages ? pageCount : 1);
- lecternTag.putInt("page", lectern.getPage() / 2);
- NbtMapBuilder bookTag = NbtMap.builder()
- .putByte("Count", (byte) book.getCount())
- .putShort("Damage", (short) 0)
- .putString("Name", "minecraft:writable_book");
- List pages = new ArrayList<>(hasBookPages ? pageCount : 1);
- if (hasBookPages) {
- List bookPages = getPages(book);
- for (String page : bookPages) {
- NbtMapBuilder pageBuilder = NbtMap.builder()
- .putString("photoname", "")
- .putString("text", page);
- pages.add(pageBuilder.build());
- }
- } else {
- // Empty page
- NbtMapBuilder pageBuilder = NbtMap.builder()
- .putString("photoname", "")
- .putString("text", "");
- pages.add(pageBuilder.build());
- }
-
- bookTag.putCompound("tag", NbtMap.builder().putList("pages", NbtType.COMPOUND, pages).build());
- lecternTag.putCompound("book", bookTag.build());
- NbtMap blockEntityTag = lecternTag.build();
- BlockEntityUtils.updateBlockEntity(session, blockEntityTag, Vector3i.from(x, y, z));
- }
-
@Override
public boolean hasPermission(GeyserSession session, String permission) {
ServerPlayer player = getPlayer(session);
@@ -263,43 +165,31 @@ public class GeyserModWorldManager extends GeyserWorldManager {
return future;
}
+ @Override
+ public void getDecoratedPotData(GeyserSession session, Vector3i pos, Consumer> apply) {
+ server.execute(() -> {
+ ServerPlayer player = getPlayer(session);
+ if (player == null) {
+ return;
+ }
+
+ BlockPos blockPos = new BlockPos(pos.getX(), pos.getY(), pos.getZ());
+ // Don't create a new block entity if invalid
+ //noinspection resource - level() is just a getter
+ BlockEntity blockEntity = player.level().getChunkAt(blockPos).getBlockEntity(blockPos);
+ if (blockEntity instanceof DecoratedPotBlockEntity pot) {
+ List sherds = pot.getDecorations().ordered()
+ .stream().map(item -> BuiltInRegistries.ITEM.getKey(item).toString())
+ .toList();
+ apply.accept(sherds);
+ }
+ });
+ }
+
private ServerPlayer getPlayer(GeyserSession session) {
return server.getPlayerList().getPlayer(session.getPlayerEntity().getUuid());
}
- private static int getPageCount(ItemStack itemStack) {
- WrittenBookContent writtenBookContent = itemStack.get(DataComponents.WRITTEN_BOOK_CONTENT);
- if (writtenBookContent != null) {
- return writtenBookContent.pages().size();
- } else {
- WritableBookContent writableBookContent = itemStack.get(DataComponents.WRITABLE_BOOK_CONTENT);
- return writableBookContent != null ? writableBookContent.pages().size() : 0;
- }
- }
-
- private static List getPages(ItemStack itemStack) {
- WrittenBookContent writtenBookContent = itemStack.get(DataComponents.WRITTEN_BOOK_CONTENT);
- if (writtenBookContent != null) {
- return writtenBookContent.pages().stream()
- .map(Filterable::raw)
- .map(GeyserModWorldManager::fromComponent)
- .toList();
- } else {
- WritableBookContent writableBookContent = itemStack.get(DataComponents.WRITABLE_BOOK_CONTENT);
- if (writableBookContent == null) {
- return List.of();
- }
- return writableBookContent.pages().stream()
- .map(Filterable::raw)
- .toList();
- }
- }
-
- private static String fromComponent(Component component) {
- String json = Component.Serializer.toJson(component, RegistryAccess.EMPTY);
- return LEGACY_SERIALIZER.serialize(GSON_SERIALIZER.deserializeOr(json, net.kyori.adventure.text.Component.empty()));
- }
-
private static net.kyori.adventure.text.Component toKyoriComponent(Component component) {
String json = Component.Serializer.toJson(component, RegistryAccess.EMPTY);
return GSON_SERIALIZER.deserializeOr(json, net.kyori.adventure.text.Component.empty());
@@ -309,7 +199,7 @@ public class GeyserModWorldManager extends GeyserWorldManager {
return patternLayers.layers().stream()
.map(layer -> {
BannerPatternLayer.BannerPattern pattern = new BannerPatternLayer.BannerPattern(
- layer.pattern().value().assetId().toString(), layer.pattern().value().translationKey()
+ MinecraftKey.key(layer.pattern().value().assetId().toString()), layer.pattern().value().translationKey()
);
return new BannerPatternLayer(Holder.ofCustom(pattern), layer.color().getId());
})
diff --git a/bootstrap/spigot/build.gradle.kts b/bootstrap/spigot/build.gradle.kts
index 8143d96a1..fcb85f100 100644
--- a/bootstrap/spigot/build.gradle.kts
+++ b/bootstrap/spigot/build.gradle.kts
@@ -4,6 +4,12 @@ dependencies {
isTransitive = false
}
+ implementation(libs.erosion.bukkit.nms) {
+ attributes {
+ attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 21)
+ }
+ }
+
implementation(variantOf(libs.adapters.spigot) {
classifier("all") // otherwise the unshaded jar is used without the shaded NMS implementations
})
@@ -70,3 +76,8 @@ tasks.withType {
exclude(dependency("com.mojang:.*"))
}
}
+
+modrinth {
+ uploadFile.set(tasks.getByPath("shadowJar"))
+ loaders.addAll("spigot", "paper")
+}
diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserPaperLogger.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserPaperLogger.java
index 930f84cec..9ebd6519a 100644
--- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserPaperLogger.java
+++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserPaperLogger.java
@@ -34,8 +34,8 @@ import java.util.logging.Logger;
public final class GeyserPaperLogger extends GeyserSpigotLogger {
private final ComponentLogger componentLogger;
- public GeyserPaperLogger(Plugin plugin, Logger logger, boolean debug) {
- super(logger, debug);
+ public GeyserPaperLogger(Plugin plugin, Logger logger) {
+ super(logger);
componentLogger = plugin.getComponentLogger();
}
diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotLogger.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotLogger.java
index fe56cba1c..5c6101eae 100644
--- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotLogger.java
+++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotLogger.java
@@ -25,15 +25,15 @@
package org.geysermc.geyser.platform.spigot;
-import lombok.AllArgsConstructor;
import lombok.Getter;
+import lombok.RequiredArgsConstructor;
import lombok.Setter;
import org.geysermc.geyser.GeyserLogger;
import java.util.logging.Level;
import java.util.logging.Logger;
-@AllArgsConstructor
+@RequiredArgsConstructor
public class GeyserSpigotLogger implements GeyserLogger {
private final Logger logger;
@Getter @Setter
diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPlugin.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPlugin.java
index e33de5f9b..2d13155f2 100644
--- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPlugin.java
+++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPlugin.java
@@ -79,14 +79,14 @@ import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;
-import java.util.logging.Level;
public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap {
private GeyserSpigotCommandManager geyserCommandManager;
private GeyserSpigotConfiguration geyserConfig;
private GeyserSpigotInjector geyserInjector;
- private GeyserSpigotLogger geyserLogger;
+ private final GeyserSpigotLogger geyserLogger = GeyserPaperLogger.supported() ?
+ new GeyserPaperLogger(this, getLogger()) : new GeyserSpigotLogger(getLogger());
private IGeyserPingPassthrough geyserSpigotPingPassthrough;
private GeyserSpigotWorldManager geyserWorldManager;
@@ -114,12 +114,12 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap {
// We depend on this as a fallback in certain scenarios
BlockData.class.getMethod("getAsString");
} catch (ClassNotFoundException | NoSuchMethodException e) {
- getLogger().severe("*********************************************");
- getLogger().severe("");
- getLogger().severe(GeyserLocale.getLocaleStringLog("geyser.bootstrap.unsupported_server.header"));
- getLogger().severe(GeyserLocale.getLocaleStringLog("geyser.bootstrap.unsupported_server.message", "1.13.2"));
- getLogger().severe("");
- getLogger().severe("*********************************************");
+ geyserLogger.error("*********************************************");
+ geyserLogger.error("");
+ geyserLogger.error(GeyserLocale.getLocaleStringLog("geyser.bootstrap.unsupported_server.header"));
+ geyserLogger.error(GeyserLocale.getLocaleStringLog("geyser.bootstrap.unsupported_server.message", "1.13.2"));
+ geyserLogger.error("");
+ geyserLogger.error("*********************************************");
Bukkit.getPluginManager().disablePlugin(this);
return;
}
@@ -128,12 +128,12 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap {
Class.forName("net.md_5.bungee.chat.ComponentSerializer");
} catch (ClassNotFoundException e) {
if (!PaperAdventure.canSendMessageUsingComponent()) { // Prepare for Paper eventually removing Bungee chat
- getLogger().severe("*********************************************");
- getLogger().severe("");
- getLogger().severe(GeyserLocale.getLocaleStringLog("geyser.bootstrap.unsupported_server_type.header", getServer().getName()));
- getLogger().severe(GeyserLocale.getLocaleStringLog("geyser.bootstrap.unsupported_server_type.message", "Paper"));
- getLogger().severe("");
- getLogger().severe("*********************************************");
+ geyserLogger.error("*********************************************");
+ geyserLogger.error("");
+ geyserLogger.error(GeyserLocale.getLocaleStringLog("geyser.bootstrap.unsupported_server_type.header", getServer().getName()));
+ geyserLogger.error(GeyserLocale.getLocaleStringLog("geyser.bootstrap.unsupported_server_type.message", "Paper"));
+ geyserLogger.error("");
+ geyserLogger.error("*********************************************");
Bukkit.getPluginManager().disablePlugin(this);
return;
}
@@ -142,11 +142,11 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap {
try {
Class.forName("io.netty.util.internal.ObjectPool$ObjectCreator");
} catch (ClassNotFoundException e) {
- getLogger().severe("*********************************************");
- getLogger().severe("");
- getLogger().severe("This version of Spigot is using an outdated version of netty. Please use Paper instead!");
- getLogger().severe("");
- getLogger().severe("*********************************************");
+ geyserLogger.error("*********************************************");
+ geyserLogger.error("");
+ geyserLogger.error("This version of Spigot is using an outdated version of netty. Please use Paper instead!");
+ geyserLogger.error("");
+ geyserLogger.error("*********************************************");
Bukkit.getPluginManager().disablePlugin(this);
return;
}
@@ -154,8 +154,7 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap {
if (!loadConfig()) {
return;
}
- this.geyserLogger = GeyserPaperLogger.supported() ? new GeyserPaperLogger(this, getLogger(), geyserConfig.isDebugMode())
- : new GeyserSpigotLogger(getLogger(), geyserConfig.isDebugMode());
+ this.geyserLogger.setDebug(geyserConfig.isDebugMode());
GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger);
// Turn "(MC: 1.16.4)" into 1.16.4.
@@ -252,6 +251,7 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap {
SpigotAdapters.registerWorldAdapter(nmsVersion);
geyserLogger.debug("Using spigot NMS adapter for nms version: " + nmsVersion);
} catch (Exception e) { // Likely running on Paper 1.20.5+
+ geyserLogger.debug("Unable to find spigot world manager: " + e.getMessage());
//noinspection deprecation
int protocolVersion = Bukkit.getUnsafe().getProtocolVersion();
PaperAdapters.registerClosestWorldAdapter(protocolVersion);
@@ -266,7 +266,7 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap {
this.geyserWorldManager = new GeyserSpigotNativeWorldManager(this, isPaper);
}
geyserLogger.debug("Using world manager of type: " + this.geyserWorldManager.getClass().getSimpleName());
- } catch (Exception e) {
+ } catch (Throwable e) {
if (geyserConfig.isDebugMode()) {
geyserLogger.debug("Error while attempting to find NMS adapter. Most likely, this can be safely ignored. :)");
e.printStackTrace();
@@ -486,7 +486,7 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap {
(x) -> x.replaceAll("generateduuid", UUID.randomUUID().toString()), this);
this.geyserConfig = FileUtils.loadConfig(configFile, GeyserSpigotConfiguration.class);
} catch (IOException ex) {
- getLogger().log(Level.SEVERE, GeyserLocale.getLocaleStringLog("geyser.config.failed"), ex);
+ geyserLogger.error(GeyserLocale.getLocaleStringLog("geyser.config.failed"), ex);
ex.printStackTrace();
Bukkit.getPluginManager().disablePlugin(this);
return false;
diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/GeyserPistonListener.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/GeyserPistonListener.java
index 61c0d5fe8..963f5bac3 100644
--- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/GeyserPistonListener.java
+++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/GeyserPistonListener.java
@@ -25,10 +25,8 @@
package org.geysermc.geyser.platform.spigot.world;
-import org.geysermc.mcprotocollib.protocol.data.game.level.block.value.PistonValueType;
-import org.cloudburstmc.math.vector.Vector3i;
-import it.unimi.dsi.fastutil.objects.Object2IntArrayMap;
-import it.unimi.dsi.fastutil.objects.Object2IntMap;
+import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap;
+import it.unimi.dsi.fastutil.objects.Object2ObjectMap;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.World;
@@ -40,13 +38,17 @@ import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockPistonEvent;
import org.bukkit.event.block.BlockPistonExtendEvent;
import org.bukkit.event.block.BlockPistonRetractEvent;
+import org.cloudburstmc.math.vector.Vector3i;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.level.block.BlockStateValues;
+import org.geysermc.geyser.level.block.property.Properties;
+import org.geysermc.geyser.level.block.type.BlockState;
import org.geysermc.geyser.level.physics.Direction;
import org.geysermc.geyser.platform.spigot.world.manager.GeyserSpigotWorldManager;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.session.cache.PistonCache;
import org.geysermc.geyser.translator.level.block.entity.PistonBlockEntity;
+import org.geysermc.mcprotocollib.protocol.data.game.level.block.value.PistonValueType;
import java.util.List;
import java.util.Map;
@@ -85,7 +87,7 @@ public class GeyserPistonListener implements Listener {
PistonValueType type = isExtend ? PistonValueType.PUSHING : PistonValueType.PULLING;
boolean sticky = event.isSticky();
- Object2IntMap attachedBlocks = new Object2IntArrayMap<>();
+ Object2ObjectMap attachedBlocks = new Object2ObjectArrayMap<>();
boolean blocksFilled = false;
for (Map.Entry entry : geyser.getSessionManager().getSessions().entrySet()) {
@@ -108,10 +110,10 @@ public class GeyserPistonListener implements Listener {
List blocks = isExtend ? ((BlockPistonExtendEvent) event).getBlocks() : ((BlockPistonRetractEvent) event).getBlocks();
for (Block block : blocks) {
Location attachedLocation = block.getLocation();
- int blockId = worldManager.getBlockNetworkId(block);
+ BlockState state = BlockState.of(worldManager.getBlockNetworkId(block));
// Ignore blocks that will be destroyed
- if (BlockStateValues.canPistonMoveBlock(blockId, isExtend)) {
- attachedBlocks.put(getVector(attachedLocation), blockId);
+ if (BlockStateValues.canPistonMoveBlock(state, isExtend)) {
+ attachedBlocks.put(getVector(attachedLocation), state);
}
}
blocksFilled = true;
@@ -119,7 +121,7 @@ public class GeyserPistonListener implements Listener {
int pistonBlockId = worldManager.getBlockNetworkId(event.getBlock());
// event.getDirection() is unreliable
- Direction orientation = BlockStateValues.getPistonOrientation(pistonBlockId);
+ Direction orientation = BlockState.of(pistonBlockId).getValue(Properties.FACING);
session.executeInEventLoop(() -> {
PistonCache pistonCache = session.getPistonCache();
diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/GeyserSpigotBlockPlaceListener.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/GeyserSpigotBlockPlaceListener.java
index 71aba11f9..1cdd77c64 100644
--- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/GeyserSpigotBlockPlaceListener.java
+++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/GeyserSpigotBlockPlaceListener.java
@@ -33,7 +33,7 @@ import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockPlaceEvent;
import org.geysermc.geyser.GeyserImpl;
-import org.geysermc.geyser.level.block.BlockStateValues;
+import org.geysermc.geyser.level.block.type.Block;
import org.geysermc.geyser.platform.spigot.world.manager.GeyserSpigotWorldManager;
import org.geysermc.geyser.registry.BlockRegistries;
import org.geysermc.geyser.session.GeyserSession;
@@ -59,11 +59,11 @@ public class GeyserSpigotBlockPlaceListener implements Listener {
event.getBlockPlaced().getX(), event.getBlockPlaced().getY(), event.getBlockPlaced().getZ())));
} else {
String javaBlockId = event.getBlockPlaced().getBlockData().getAsString();
- placeBlockSoundPacket.setExtraData(session.getBlockMappings().getBedrockBlockId(BlockRegistries.JAVA_IDENTIFIER_TO_ID.get().getOrDefault(javaBlockId, BlockStateValues.JAVA_AIR_ID)));
+ placeBlockSoundPacket.setExtraData(session.getBlockMappings().getBedrockBlockId(BlockRegistries.JAVA_IDENTIFIER_TO_ID.get().getOrDefault(javaBlockId, Block.JAVA_AIR_ID)));
}
placeBlockSoundPacket.setIdentifier(":");
session.sendUpstreamPacket(placeBlockSoundPacket);
session.setLastBlockPlacePosition(null);
- session.setLastBlockPlacedId(null);
+ session.setLastBlockPlaced(null);
}
}
diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/manager/GeyserSpigotNativeWorldManager.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/manager/GeyserSpigotNativeWorldManager.java
index 45e84d254..c99ca4e78 100644
--- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/manager/GeyserSpigotNativeWorldManager.java
+++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/manager/GeyserSpigotNativeWorldManager.java
@@ -34,6 +34,7 @@ import org.geysermc.geyser.adapters.WorldAdapter;
import org.geysermc.geyser.adapters.paper.PaperAdapters;
import org.geysermc.geyser.adapters.spigot.SpigotAdapters;
import org.geysermc.geyser.level.block.BlockStateValues;
+import org.geysermc.geyser.level.block.type.Block;
import org.geysermc.geyser.session.GeyserSession;
public class GeyserSpigotNativeWorldManager extends GeyserSpigotWorldManager {
@@ -52,7 +53,7 @@ public class GeyserSpigotNativeWorldManager extends GeyserSpigotWorldManager {
public int getBlockAt(GeyserSession session, int x, int y, int z) {
Player player = Bukkit.getPlayer(session.getPlayerEntity().getUsername());
if (player == null) {
- return BlockStateValues.JAVA_AIR_ID;
+ return Block.JAVA_AIR_ID;
}
return adapter.getBlockAt(player.getWorld(), x, y, z);
}
diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/manager/GeyserSpigotWorldManager.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/manager/GeyserSpigotWorldManager.java
index 8a0e0b70d..73356c4e7 100644
--- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/manager/GeyserSpigotWorldManager.java
+++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/manager/GeyserSpigotWorldManager.java
@@ -25,55 +25,52 @@
package org.geysermc.geyser.platform.spigot.world.manager;
-import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode;
-import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents;
-import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityInfo;
+import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import org.bukkit.Bukkit;
-import org.bukkit.Chunk;
import org.bukkit.World;
import org.bukkit.block.Block;
+import org.bukkit.block.DecoratedPot;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
-import org.cloudburstmc.nbt.NbtMap;
-import org.geysermc.erosion.bukkit.BukkitLecterns;
+import org.cloudburstmc.math.vector.Vector3i;
import org.geysermc.erosion.bukkit.BukkitUtils;
+import org.geysermc.erosion.bukkit.PickBlockUtils;
import org.geysermc.erosion.bukkit.SchedulerUtils;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.level.GameRule;
import org.geysermc.geyser.level.WorldManager;
-import org.geysermc.geyser.level.block.BlockStateValues;
import org.geysermc.geyser.registry.BlockRegistries;
import org.geysermc.geyser.session.GeyserSession;
-import org.geysermc.geyser.util.BlockEntityUtils;
+import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode;
+import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
+import java.util.function.Consumer;
/**
* The base world manager to use when there is no supported NMS revision
*/
public class GeyserSpigotWorldManager extends WorldManager {
private final Plugin plugin;
- private final BukkitLecterns lecterns;
public GeyserSpigotWorldManager(Plugin plugin) {
this.plugin = plugin;
- this.lecterns = new BukkitLecterns(plugin);
}
@Override
public int getBlockAt(GeyserSession session, int x, int y, int z) {
Player bukkitPlayer;
if ((bukkitPlayer = Bukkit.getPlayer(session.getPlayerEntity().getUsername())) == null) {
- return BlockStateValues.JAVA_AIR_ID;
+ return org.geysermc.geyser.level.block.type.Block.JAVA_AIR_ID;
}
World world = bukkitPlayer.getWorld();
if (!world.isChunkLoaded(x >> 4, z >> 4)) {
// If the chunk isn't loaded, how could we even be here?
- return BlockStateValues.JAVA_AIR_ID;
+ return org.geysermc.geyser.level.block.type.Block.JAVA_AIR_ID;
}
return getBlockNetworkId(world.getBlockAt(x, y, z));
@@ -84,9 +81,9 @@ public class GeyserSpigotWorldManager extends WorldManager {
// Terrible behavior, but this is basically what's always been happening behind the scenes anyway.
CompletableFuture blockData = new CompletableFuture<>();
Bukkit.getRegionScheduler().execute(this.plugin, block.getLocation(), () -> blockData.complete(block.getBlockData().getAsString()));
- return BlockRegistries.JAVA_IDENTIFIER_TO_ID.getOrDefault(blockData.join(), BlockStateValues.JAVA_AIR_ID);
+ return BlockRegistries.JAVA_IDENTIFIER_TO_ID.getOrDefault(blockData.join(), org.geysermc.geyser.level.block.type.Block.JAVA_AIR_ID);
}
- return BlockRegistries.JAVA_IDENTIFIER_TO_ID.getOrDefault(block.getBlockData().getAsString(), BlockStateValues.JAVA_AIR_ID);
+ return BlockRegistries.JAVA_IDENTIFIER_TO_ID.getOrDefault(block.getBlockData().getAsString(), org.geysermc.geyser.level.block.type.Block.JAVA_AIR_ID); // TODO could just make this a BlockState lookup?
}
@Override
@@ -94,69 +91,6 @@ public class GeyserSpigotWorldManager extends WorldManager {
return true;
}
- @Override
- public void sendLecternData(GeyserSession session, int x, int y, int z) {
- Player bukkitPlayer;
- if ((bukkitPlayer = Bukkit.getPlayer(session.getPlayerEntity().getUsername())) == null) {
- return;
- }
-
- Block block = bukkitPlayer.getWorld().getBlockAt(x, y, z);
- // Run as a task to prevent async issues
- SchedulerUtils.runTask(this.plugin, () -> sendLecternData(session, block, false), block);
- }
-
- public void sendLecternData(GeyserSession session, int x, int z, List blockEntityInfos) {
- Player bukkitPlayer;
- if ((bukkitPlayer = Bukkit.getPlayer(session.getPlayerEntity().getUsername())) == null) {
- return;
- }
- if (SchedulerUtils.FOLIA) {
- Chunk chunk = getChunk(bukkitPlayer.getWorld(), x, z);
- if (chunk == null) {
- return;
- }
- Bukkit.getRegionScheduler().execute(this.plugin, bukkitPlayer.getWorld(), x, z, () ->
- sendLecternData(session, chunk, blockEntityInfos));
- } else {
- Bukkit.getScheduler().runTask(this.plugin, () -> {
- Chunk chunk = getChunk(bukkitPlayer.getWorld(), x, z);
- if (chunk == null) {
- return;
- }
- sendLecternData(session, chunk, blockEntityInfos);
- });
- }
- }
-
- private @Nullable Chunk getChunk(World world, int x, int z) {
- if (!world.isChunkLoaded(x, z)) {
- return null;
- }
- return world.getChunkAt(x, z);
- }
-
- private void sendLecternData(GeyserSession session, Chunk chunk, List blockEntityInfos) {
- //noinspection ForLoopReplaceableByForEach - avoid constructing Iterator
- for (int i = 0; i < blockEntityInfos.size(); i++) {
- BlockEntityInfo info = blockEntityInfos.get(i);
- Block block = chunk.getBlock(info.getX(), info.getY(), info.getZ());
- sendLecternData(session, block, true);
- }
- }
-
- private void sendLecternData(GeyserSession session, Block block, boolean isChunkLoad) {
- NbtMap blockEntityTag = this.lecterns.getLecternData(block, isChunkLoad);
- if (blockEntityTag != null) {
- BlockEntityUtils.updateBlockEntity(session, blockEntityTag, BukkitUtils.getVector(block.getLocation()));
- }
- }
-
- @Override
- public boolean shouldExpectLecternHandled(GeyserSession session) {
- return true;
- }
-
public boolean getGameRuleBool(GeyserSession session, GameRule gameRule) {
org.bukkit.GameRule> bukkitGameRule = org.bukkit.GameRule.getByName(gameRule.getJavaID());
if (bukkitGameRule == null) {
@@ -205,17 +139,31 @@ public class GeyserSpigotWorldManager extends WorldManager {
@Override
public @NonNull CompletableFuture<@Nullable DataComponents> getPickItemComponents(GeyserSession session, int x, int y, int z, boolean addNbtData) {
- CompletableFuture<@Nullable DataComponents> future = new CompletableFuture<>();
Player bukkitPlayer;
if ((bukkitPlayer = Bukkit.getPlayer(session.getPlayerEntity().getUuid())) == null) {
- future.complete(null);
- return future;
+ return CompletableFuture.completedFuture(null);
}
+ CompletableFuture> future = new CompletableFuture<>();
Block block = bukkitPlayer.getWorld().getBlockAt(x, y, z);
// Paper 1.19.3 complains about async access otherwise.
// java.lang.IllegalStateException: Tile is null, asynchronous access?
- SchedulerUtils.runTask(this.plugin, () -> future.complete(/*PickBlockUtils.pickBlock(block)*/ null), block); // TODO fix erosion once clear how to handle this
- return future;
+ SchedulerUtils.runTask(this.plugin, () -> future.complete(PickBlockUtils.pickBlock(block)), block);
+ return future.thenApply(RAW_TRANSFORMER);
+ }
+
+ public void getDecoratedPotData(GeyserSession session, Vector3i pos, Consumer> apply) {
+ Player bukkitPlayer;
+ if ((bukkitPlayer = Bukkit.getPlayer(session.getPlayerEntity().getUuid())) == null) {
+ return;
+ }
+ Block block = bukkitPlayer.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ());
+ SchedulerUtils.runTask(this.plugin, () -> {
+ var state = BukkitUtils.getBlockState(block);
+ if (!(state instanceof DecoratedPot pot)) {
+ return;
+ }
+ apply.accept(pot.getShards().stream().map(material -> material.getKey().toString()).toList());
+ }, block);
}
/**
diff --git a/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/GeyserStandaloneBootstrap.java b/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/GeyserStandaloneBootstrap.java
index 039004867..f289fa2ba 100644
--- a/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/GeyserStandaloneBootstrap.java
+++ b/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/GeyserStandaloneBootstrap.java
@@ -71,7 +71,7 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap {
private GeyserCommandManager geyserCommandManager;
private GeyserStandaloneConfiguration geyserConfig;
- private GeyserStandaloneLogger geyserLogger;
+ private final GeyserStandaloneLogger geyserLogger = new GeyserStandaloneLogger();
private IGeyserPingPassthrough geyserPingPassthrough;
private GeyserStandaloneGUI gui;
@Getter
@@ -181,8 +181,6 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap {
}
}
- this.geyserLogger = new GeyserStandaloneLogger();
-
if (useGui && gui == null) {
gui = new GeyserStandaloneGUI(geyserLogger);
gui.redirectSystemStreams();
diff --git a/bootstrap/velocity/build.gradle.kts b/bootstrap/velocity/build.gradle.kts
index da826803c..4daad9784 100644
--- a/bootstrap/velocity/build.gradle.kts
+++ b/bootstrap/velocity/build.gradle.kts
@@ -69,4 +69,9 @@ tasks.withType {
exclude(dependency("net.kyori:adventure-text-serializer-legacy:.*"))
exclude(dependency("net.kyori:adventure-nbt:.*"))
}
+}
+
+modrinth {
+ uploadFile.set(tasks.getByPath("shadowJar"))
+ loaders.addAll("velocity")
}
\ No newline at end of file
diff --git a/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityLogger.java b/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityLogger.java
index 567870e7f..4d10e4daf 100644
--- a/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityLogger.java
+++ b/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityLogger.java
@@ -25,13 +25,13 @@
package org.geysermc.geyser.platform.velocity;
-import lombok.AllArgsConstructor;
import lombok.Getter;
+import lombok.RequiredArgsConstructor;
import lombok.Setter;
import org.geysermc.geyser.GeyserLogger;
import org.slf4j.Logger;
-@AllArgsConstructor
+@RequiredArgsConstructor
public class GeyserVelocityLogger implements GeyserLogger {
private final Logger logger;
@Getter @Setter
diff --git a/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityPlugin.java b/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityPlugin.java
index 347a47d63..539bdadbf 100644
--- a/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityPlugin.java
+++ b/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityPlugin.java
@@ -64,44 +64,44 @@ import java.util.UUID;
@Plugin(id = "geyser", name = GeyserImpl.NAME + "-Velocity", version = GeyserImpl.VERSION, url = "https://geysermc.org", authors = "GeyserMC")
public class GeyserVelocityPlugin implements GeyserBootstrap {
- @Inject
- private Logger logger;
-
- @Inject
- private ProxyServer proxyServer;
-
- @Inject
- private CommandManager commandManager;
+ private final ProxyServer proxyServer;
+ private final CommandManager commandManager;
+ private final GeyserVelocityLogger geyserLogger;
private GeyserCommandManager geyserCommandManager;
private GeyserVelocityConfiguration geyserConfig;
private GeyserVelocityInjector geyserInjector;
- private GeyserVelocityLogger geyserLogger;
private IGeyserPingPassthrough geyserPingPassthrough;
-
private GeyserImpl geyser;
@Getter
private final Path configFolder = Paths.get("plugins/" + GeyserImpl.NAME + "-Velocity/");
+ @Inject
+ public GeyserVelocityPlugin(ProxyServer server, Logger logger, CommandManager manager) {
+ this.geyserLogger = new GeyserVelocityLogger(logger);
+ this.proxyServer = server;
+ this.commandManager = manager;
+ }
+
@Override
public void onGeyserInitialize() {
GeyserLocale.init(this);
if (!ProtocolVersion.isSupported(GameProtocol.getJavaProtocolVersion())) {
- logger.error(" / \\");
- logger.error(" / \\");
- logger.error(" / | \\");
- logger.error(" / | \\ " + GeyserLocale.getLocaleStringLog("geyser.bootstrap.unsupported_proxy", proxyServer.getVersion().getName()));
- logger.error(" / \\ " + GeyserLocale.getLocaleStringLog("geyser.may_not_work_as_intended_all_caps"));
- logger.error(" / o \\");
- logger.error("/_____________\\");
+ geyserLogger.error(" / \\");
+ geyserLogger.error(" / \\");
+ geyserLogger.error(" / | \\");
+ geyserLogger.error(" / | \\ " + GeyserLocale.getLocaleStringLog("geyser.bootstrap.unsupported_proxy", proxyServer.getVersion().getName()));
+ geyserLogger.error(" / \\ " + GeyserLocale.getLocaleStringLog("geyser.may_not_work_as_intended_all_caps"));
+ geyserLogger.error(" / o \\");
+ geyserLogger.error("/_____________\\");
}
if (!loadConfig()) {
return;
}
- this.geyserLogger = new GeyserVelocityLogger(logger, geyserConfig.isDebugMode());
+ this.geyserLogger.setDebug(geyserConfig.isDebugMode());
GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger);
this.geyser = GeyserImpl.load(PlatformType.VELOCITY, this);
@@ -249,7 +249,7 @@ public class GeyserVelocityPlugin implements GeyserBootstrap {
"config.yml", (x) -> x.replaceAll("generateduuid", UUID.randomUUID().toString()), this);
this.geyserConfig = FileUtils.loadConfig(configFile, GeyserVelocityConfiguration.class);
} catch (IOException ex) {
- logger.error(GeyserLocale.getLocaleStringLog("geyser.config.failed"), ex);
+ geyserLogger.error(GeyserLocale.getLocaleStringLog("geyser.config.failed"), ex);
ex.printStackTrace();
return false;
}
diff --git a/bootstrap/viaproxy/src/main/java/org/geysermc/geyser/platform/viaproxy/GeyserViaProxyConfiguration.java b/bootstrap/viaproxy/src/main/java/org/geysermc/geyser/platform/viaproxy/GeyserViaProxyConfiguration.java
index bf9d6816c..afc46fa6a 100644
--- a/bootstrap/viaproxy/src/main/java/org/geysermc/geyser/platform/viaproxy/GeyserViaProxyConfiguration.java
+++ b/bootstrap/viaproxy/src/main/java/org/geysermc/geyser/platform/viaproxy/GeyserViaProxyConfiguration.java
@@ -27,14 +27,23 @@ package org.geysermc.geyser.platform.viaproxy;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import net.raphimc.vialegacy.api.LegacyProtocolVersion;
import net.raphimc.viaproxy.ViaProxy;
+import net.raphimc.viaproxy.protocoltranslator.viaproxy.ViaProxyConfig;
import org.geysermc.geyser.configuration.GeyserJacksonConfiguration;
import java.io.File;
import java.nio.file.Path;
@JsonIgnoreProperties(ignoreUnknown = true)
+@SuppressWarnings("FieldMayBeFinal") // Jackson requires that the fields are not final
public class GeyserViaProxyConfiguration extends GeyserJacksonConfiguration {
+ private RemoteConfiguration remote = new RemoteConfiguration() {
+ @Override
+ public boolean isForwardHost() {
+ return super.isForwardHost() || !ViaProxy.getConfig().getWildcardDomainHandling().equals(ViaProxyConfig.WildcardDomainHandling.NONE);
+ }
+ };
+
@Override
public Path getFloodgateKeyPath() {
return new File(GeyserViaProxyPlugin.ROOT_FOLDER, this.getFloodgateKeyFile()).toPath();
@@ -50,4 +59,9 @@ public class GeyserViaProxyConfiguration extends GeyserJacksonConfiguration {
return interval;
}
+ @Override
+ public RemoteConfiguration getRemote() {
+ return this.remote;
+ }
+
}
diff --git a/bootstrap/viaproxy/src/main/java/org/geysermc/geyser/platform/viaproxy/GeyserViaProxyPlugin.java b/bootstrap/viaproxy/src/main/java/org/geysermc/geyser/platform/viaproxy/GeyserViaProxyPlugin.java
index 30404e705..bdc80335a 100644
--- a/bootstrap/viaproxy/src/main/java/org/geysermc/geyser/platform/viaproxy/GeyserViaProxyPlugin.java
+++ b/bootstrap/viaproxy/src/main/java/org/geysermc/geyser/platform/viaproxy/GeyserViaProxyPlugin.java
@@ -37,6 +37,7 @@ import org.apache.logging.log4j.LogManager;
import org.geysermc.geyser.GeyserBootstrap;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.GeyserLogger;
+import org.geysermc.geyser.api.event.EventRegistrar;
import org.geysermc.geyser.api.network.AuthType;
import org.geysermc.geyser.api.util.PlatformType;
import org.geysermc.geyser.command.GeyserCommandManager;
@@ -44,6 +45,7 @@ import org.geysermc.geyser.configuration.GeyserConfiguration;
import org.geysermc.geyser.dump.BootstrapDumpInfo;
import org.geysermc.geyser.ping.GeyserLegacyPingPassthrough;
import org.geysermc.geyser.ping.IGeyserPingPassthrough;
+import org.geysermc.geyser.platform.viaproxy.listener.GeyserServerTransferListener;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.text.GeyserLocale;
import org.geysermc.geyser.util.FileUtils;
@@ -57,7 +59,7 @@ import java.nio.file.Files;
import java.nio.file.Path;
import java.util.UUID;
-public class GeyserViaProxyPlugin extends ViaProxyPlugin implements GeyserBootstrap {
+public class GeyserViaProxyPlugin extends ViaProxyPlugin implements GeyserBootstrap, EventRegistrar {
public static final File ROOT_FOLDER = new File(PluginManager.PLUGINS_DIR, "Geyser");
@@ -120,6 +122,7 @@ public class GeyserViaProxyPlugin extends ViaProxyPlugin implements GeyserBootst
}
this.geyser = GeyserImpl.load(PlatformType.VIAPROXY, this);
+ this.geyser.eventBus().register(this, new GeyserServerTransferListener());
LoopbackUtil.checkAndApplyLoopback(this.logger);
}
diff --git a/bootstrap/viaproxy/src/main/java/org/geysermc/geyser/platform/viaproxy/listener/GeyserServerTransferListener.java b/bootstrap/viaproxy/src/main/java/org/geysermc/geyser/platform/viaproxy/listener/GeyserServerTransferListener.java
new file mode 100644
index 000000000..64b3cc56e
--- /dev/null
+++ b/bootstrap/viaproxy/src/main/java/org/geysermc/geyser/platform/viaproxy/listener/GeyserServerTransferListener.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2024 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.platform.viaproxy.listener;
+
+import com.google.common.cache.Cache;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.net.HostAndPort;
+import org.geysermc.event.PostOrder;
+import org.geysermc.event.subscribe.Subscribe;
+import org.geysermc.geyser.api.event.bedrock.SessionLoginEvent;
+import org.geysermc.geyser.api.event.java.ServerTransferEvent;
+import org.geysermc.geyser.session.GeyserSession;
+
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+public class GeyserServerTransferListener {
+
+ private final Cache> cookieStorages = CacheBuilder.newBuilder().expireAfterWrite(1, TimeUnit.MINUTES).build();
+
+ @Subscribe(postOrder = PostOrder.FIRST)
+ private void onServerTransfer(final ServerTransferEvent event) {
+ this.cookieStorages.put(event.connection().xuid(), event.cookies());
+ final GeyserSession geyserSession = (GeyserSession) event.connection();
+ final HostAndPort hostAndPort = HostAndPort.fromString(geyserSession.getClientData().getServerAddress()).withDefaultPort(19132);
+ event.bedrockHost(hostAndPort.getHost());
+ event.bedrockPort(hostAndPort.getPort());
+ }
+
+ @Subscribe(postOrder = PostOrder.FIRST)
+ private void onSessionLogin(final SessionLoginEvent event) {
+ final Map cookies = this.cookieStorages.asMap().remove(event.connection().xuid());
+ if (cookies != null) {
+ event.cookies(cookies);
+ event.transferring(true);
+ }
+ }
+
+}
diff --git a/build-logic/build.gradle.kts b/build-logic/build.gradle.kts
index b7aab2bf0..190386667 100644
--- a/build-logic/build.gradle.kts
+++ b/build-logic/build.gradle.kts
@@ -12,6 +12,9 @@ repositories {
}
dependencies {
+ // this is OK as long as the same version catalog is used in the main build and build-logic
+ // see https://github.com/gradle/gradle/issues/15383#issuecomment-779893192
+ implementation(files(libs.javaClass.superclass.protectionDomain.codeSource.location))
implementation(libs.indra)
implementation(libs.shadow)
implementation(libs.architectury.plugin)
diff --git a/build-logic/src/main/kotlin/LibsAccessor.kt b/build-logic/src/main/kotlin/LibsAccessor.kt
new file mode 100644
index 000000000..2a0c09eb6
--- /dev/null
+++ b/build-logic/src/main/kotlin/LibsAccessor.kt
@@ -0,0 +1,6 @@
+import org.gradle.accessors.dm.LibrariesForLibs
+import org.gradle.api.Project
+import org.gradle.kotlin.dsl.getByType
+
+val Project.libs: LibrariesForLibs
+ get() = rootProject.extensions.getByType()
\ No newline at end of file
diff --git a/build-logic/src/main/kotlin/geyser.modded-conventions.gradle.kts b/build-logic/src/main/kotlin/geyser.modded-conventions.gradle.kts
index b75e9c5be..7952bcf14 100644
--- a/build-logic/src/main/kotlin/geyser.modded-conventions.gradle.kts
+++ b/build-logic/src/main/kotlin/geyser.modded-conventions.gradle.kts
@@ -8,7 +8,6 @@ plugins {
id("geyser.publish-conventions")
id("architectury-plugin")
id("dev.architectury.loom")
- id("com.modrinth.minotaur")
}
// These are provided by Minecraft/modded platforms already, no need to include them
@@ -39,7 +38,7 @@ provided("io.netty", "netty-resolver-dns-native-macos")
provided("org.ow2.asm", "asm")
architectury {
- minecraft = "1.20.5"
+ minecraft = libs.minecraft.get().version as String
}
loom {
@@ -83,7 +82,7 @@ tasks {
register("remapModrinthJar", RemapJarTask::class) {
dependsOn(shadowJar)
inputFile.set(shadowJar.get().archiveFile)
- archiveVersion.set(project.version.toString() + "+build." + System.getenv("GITHUB_RUN_NUMBER"))
+ archiveVersion.set(project.version.toString() + "+build." + System.getenv("BUILD_NUMBER"))
archiveClassifier.set("")
}
}
@@ -93,7 +92,7 @@ afterEvaluate {
// These are shaded, no need to JiJ them
configurations["shadow"].dependencies.forEach {shadowed ->
- println("Not including shadowed dependency: ${shadowed.group}:${shadowed.name}")
+ //println("Not including shadowed dependency: ${shadowed.group}:${shadowed.name}")
providedDependencies.add("${shadowed.group}:${shadowed.name}")
}
@@ -101,39 +100,24 @@ afterEvaluate {
configurations["includeTransitive"].resolvedConfiguration.resolvedArtifacts.forEach { dep ->
if (!providedDependencies.contains("${dep.moduleVersion.id.group}:${dep.moduleVersion.id.name}")
and !providedDependencies.contains("${dep.moduleVersion.id.group}:.*")) {
- println("Including dependency via JiJ: ${dep.id}")
+ //println("Including dependency via JiJ: ${dep.id}")
dependencies.add("include", dep.moduleVersion.id.toString())
} else {
- println("Not including ${dep.id} for ${project.name}!")
+ //println("Not including ${dep.id} for ${project.name}!")
}
}
}
dependencies {
- minecraft("com.mojang:minecraft:1.20.5")
+ minecraft(libs.minecraft)
mappings(loom.officialMojangMappings())
}
repositories {
// mavenLocal()
- maven("https://repo.opencollab.dev/maven-releases/")
- maven("https://repo.opencollab.dev/maven-snapshots/")
+ maven("https://repo.opencollab.dev/main")
maven("https://jitpack.io")
maven("https://oss.sonatype.org/content/repositories/snapshots/")
maven("https://s01.oss.sonatype.org/content/repositories/snapshots/")
maven("https://maven.neoforged.net/releases")
-}
-
-modrinth {
- token.set(System.getenv("MODRINTH_TOKEN")) // Even though this is the default value, apparently this prevents GitHub Actions caching the token?
- projectId.set("wKkoqHrH")
- versionNumber.set(project.version as String + "-" + System.getenv("GITHUB_RUN_NUMBER"))
- versionType.set("beta")
- changelog.set("A changelog can be found at https://github.com/GeyserMC/Geyser/commits")
-
- syncBodyFrom.set(rootProject.file("README.md").readText())
-
- uploadFile.set(tasks.getByPath("remapModrinthJar"))
- gameVersions.addAll("1.20.5", "1.20.6")
- failSilently.set(true)
}
\ No newline at end of file
diff --git a/build-logic/src/main/kotlin/geyser.modrinth-uploading-conventions.gradle.kts b/build-logic/src/main/kotlin/geyser.modrinth-uploading-conventions.gradle.kts
new file mode 100644
index 000000000..d710ae1a2
--- /dev/null
+++ b/build-logic/src/main/kotlin/geyser.modrinth-uploading-conventions.gradle.kts
@@ -0,0 +1,18 @@
+plugins {
+ id("com.modrinth.minotaur")
+}
+
+// Ensure that the readme is synched
+tasks.modrinth.get().dependsOn(tasks.modrinthSyncBody)
+
+modrinth {
+ token.set(System.getenv("MODRINTH_TOKEN") ?: "") // Even though this is the default value, apparently this prevents GitHub Actions caching the token?
+ projectId.set("geyser")
+ versionNumber.set(project.version as String + "-" + System.getenv("BUILD_NUMBER"))
+ versionType.set("beta")
+ changelog.set(System.getenv("CHANGELOG") ?: "")
+ gameVersions.add(libs.minecraft.get().version as String)
+ failSilently.set(true)
+
+ syncBodyFrom.set(rootProject.file("README.md").readText())
+}
\ No newline at end of file
diff --git a/build.gradle.kts b/build.gradle.kts
index dfdff2187..dfbf9837f 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -26,6 +26,14 @@ val moddedPlatforms = setOf(
projects.mod
).map { it.dependencyProject }
+val modrinthPlatforms = setOf(
+ projects.bungeecord,
+ projects.fabric,
+ projects.neoforge,
+ projects.spigot,
+ projects.velocity
+).map { it.dependencyProject }
+
subprojects {
apply {
plugin("java-library")
@@ -38,4 +46,10 @@ subprojects {
in moddedPlatforms -> plugins.apply("geyser.modded-conventions")
else -> plugins.apply("geyser.base-conventions")
}
+
+ // Not combined with platform-conventions as that also contains
+ // platforms which we cant publish to modrinth
+ if (modrinthPlatforms.contains(this)) {
+ plugins.apply("geyser.modrinth-uploading-conventions")
+ }
}
\ No newline at end of file
diff --git a/core/build.gradle.kts b/core/build.gradle.kts
index 42d4e13c5..fe2576462 100644
--- a/core/build.gradle.kts
+++ b/core/build.gradle.kts
@@ -1,6 +1,6 @@
-import net.kyori.blossom.BlossomExtension
-
plugins {
+ // Allow blossom to mark sources root of templates
+ idea
alias(libs.plugins.blossom)
id("geyser.publish-conventions")
}
@@ -24,7 +24,6 @@ dependencies {
implementation(libs.websocket)
api(libs.bundles.protocol)
- implementation(libs.blockstateupdater)
api(libs.mcauthlib)
api(libs.mcprotocollib) {
@@ -76,7 +75,7 @@ tasks.processResources {
expand(
"branch" to info.branch,
"buildNumber" to info.buildNumber,
- "projectVersion" to project.version,
+ "projectVersion" to info.version,
"commit" to info.commit,
"commitAbbrev" to info.commitAbbrev,
"commitMessage" to info.commitMessage,
@@ -85,21 +84,30 @@ tasks.processResources {
}
}
-configure {
- val mainFile = "src/main/java/org/geysermc/geyser/GeyserImpl.java"
- val info = GitInfo()
-
- replaceToken("\${version}", "${project.version} (${info.gitVersion})", mainFile)
- replaceToken("\${gitVersion}", info.gitVersion, mainFile)
- replaceToken("\${buildNumber}", info.buildNumber, mainFile)
- replaceToken("\${branch}", info.branch, mainFile)
- replaceToken("\${commit}", info.commit, mainFile)
- replaceToken("\${repository}", info.repository, mainFile)
+sourceSets {
+ main {
+ blossom {
+ val info = GitInfo()
+ javaSources {
+ property("version", "${info.version} (${info.gitVersion})")
+ property("gitVersion", info.gitVersion)
+ property("buildNumber", info.buildNumber.toString())
+ property("branch", info.branch)
+ property("commit", info.commit)
+ property("repository", info.repository)
+ property("devVersion", info.isDev.toString())
+ }
+ }
+ }
}
-fun Project.buildNumber(): Int =
+fun buildNumber(): Int =
(System.getenv("BUILD_NUMBER"))?.let { Integer.parseInt(it) } ?: -1
+fun isDevBuild(branch: String, repository: String): Boolean {
+ return branch != "master" || repository.equals("https://github.com/GeyserMC/Geyser", ignoreCase = true).not()
+}
+
inner class GitInfo {
val branch: String
val commit: String
@@ -112,22 +120,25 @@ inner class GitInfo {
val commitMessage: String
val repository: String
+ val isDev: Boolean
+
init {
- // On Jenkins, a detached head is checked out, so indra cannot determine the branch.
- // Fortunately, this environment variable is available.
- branch = indraGit.branchName() ?: System.getenv("BRANCH_NAME") ?: "DEV"
+ branch = indraGit.branchName() ?: "DEV"
val commit = indraGit.commit()
this.commit = commit?.name ?: "0".repeat(40)
commitAbbrev = commit?.name?.substring(0, 7) ?: "0".repeat(7)
gitVersion = "git-${branch}-${commitAbbrev}"
- version = "${project.version} ($gitVersion)"
- buildNumber = buildNumber()
val git = indraGit.git()
commitMessage = git?.commit()?.message ?: ""
repository = git?.repository?.config?.getString("remote", "origin", "url") ?: ""
+
+ buildNumber = buildNumber()
+ isDev = isDevBuild(branch, repository)
+ val projectVersion = if (isDev) project.version else project.version.toString().replace("SNAPSHOT", "b${buildNumber}")
+ version = "$projectVersion ($gitVersion)"
}
}
diff --git a/core/src/main/java/org/geysermc/geyser/level/block/DoubleChestValue.java b/core/src/main/java-templates/org/geysermc/geyser/BuildData.java
similarity index 66%
rename from core/src/main/java/org/geysermc/geyser/level/block/DoubleChestValue.java
rename to core/src/main/java-templates/org/geysermc/geyser/BuildData.java
index 97c861df7..0e4d08bfe 100644
--- a/core/src/main/java/org/geysermc/geyser/level/block/DoubleChestValue.java
+++ b/core/src/main/java-templates/org/geysermc/geyser/BuildData.java
@@ -23,18 +23,20 @@
* @link https://github.com/GeyserMC/Geyser
*/
-package org.geysermc.geyser.level.block;
+package org.geysermc.geyser;
-/**
- * This stores all values of double chests that are part of the Java block state.
- *
- * @param isFacingEast If true, then chest is facing east/west; if false, south/north
- * @param isDirectionPositive If true, direction is positive (east/south); if false, direction is negative (west/north)
- * @param isLeft If true, chest is the left of a pair; if false, chest is the right of a pair.
- */
-public record DoubleChestValue(
- boolean isFacingEast,
- boolean isDirectionPositive,
- boolean isLeft) {
+// The constants are replaced before compilation
+public class BuildData {
+ public static final String GIT_VERSION = "{{ gitVersion }}";
+ public static final String VERSION = "{{ version }}";
+ public static final String BUILD_NUMBER = "{{ buildNumber }}";
+ public static final String BRANCH = "{{ branch }}";
+ public static final String COMMIT = "{{ commit }}";
+ public static final String REPOSITORY = "{{ repository }}";
+ private static final String DEV = "{{ devVersion }}";
+
+ public static boolean isDevBuild() {
+ return Boolean.parseBoolean(DEV);
+ }
}
diff --git a/core/src/main/java/org/geysermc/geyser/Constants.java b/core/src/main/java/org/geysermc/geyser/Constants.java
index 5de8e6e6b..588b25172 100644
--- a/core/src/main/java/org/geysermc/geyser/Constants.java
+++ b/core/src/main/java/org/geysermc/geyser/Constants.java
@@ -34,7 +34,7 @@ public final class Constants {
public static final String NEWS_OVERVIEW_URL = "https://api.geysermc.org/v2/news/";
public static final String NEWS_PROJECT_NAME = "geyser";
- public static final String FLOODGATE_DOWNLOAD_LOCATION = "https://ci.opencollab.dev/job/GeyserMC/job/Floodgate/job/master/";
+ public static final String FLOODGATE_DOWNLOAD_LOCATION = "https://geysermc.org/download#floodgate";
public static final String GEYSER_DOWNLOAD_LOCATION = "https://geysermc.org/download";
public static final String UPDATE_PERMISSION = "geyser.update";
diff --git a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java
index d5635acf9..a3eeca6a5 100644
--- a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java
+++ b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java
@@ -45,6 +45,7 @@ import org.cloudburstmc.protocol.bedrock.codec.BedrockCodec;
import org.geysermc.api.Geyser;
import org.geysermc.cumulus.form.Form;
import org.geysermc.cumulus.form.util.FormBuilder;
+import org.geysermc.erosion.packet.Packets;
import org.geysermc.floodgate.crypto.AesCipher;
import org.geysermc.floodgate.crypto.AesKeyProducer;
import org.geysermc.floodgate.crypto.Base64Topping;
@@ -77,6 +78,7 @@ import org.geysermc.geyser.scoreboard.ScoreboardUpdater;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.session.PendingMicrosoftAuthentication;
import org.geysermc.geyser.session.SessionManager;
+import org.geysermc.geyser.session.cache.RegistryCache;
import org.geysermc.geyser.skin.FloodgateSkinUploader;
import org.geysermc.geyser.skin.ProvidedSkins;
import org.geysermc.geyser.skin.SkinProvider;
@@ -113,13 +115,14 @@ public class GeyserImpl implements GeyserApi {
.enable(JsonParser.Feature.ALLOW_SINGLE_QUOTES);
public static final String NAME = "Geyser";
- public static final String GIT_VERSION = "${gitVersion}";
- public static final String VERSION = "${version}";
+ public static final String GIT_VERSION = BuildData.GIT_VERSION;
+ public static final String VERSION = BuildData.VERSION;
- public static final String BUILD_NUMBER = "${buildNumber}";
- public static final String BRANCH = "${branch}";
- public static final String COMMIT = "${commit}";
- public static final String REPOSITORY = "${repository}";
+ public static final String BUILD_NUMBER = BuildData.BUILD_NUMBER;
+ public static final String BRANCH = BuildData.BRANCH;
+ public static final String COMMIT = BuildData.COMMIT;
+ public static final String REPOSITORY = BuildData.REPOSITORY;
+ public static final boolean IS_DEV = BuildData.isDevBuild();
/**
* Oauth client ID for Microsoft authentication
@@ -205,12 +208,20 @@ public class GeyserImpl implements GeyserApi {
logger.info("");
logger.info(GeyserLocale.getLocaleStringLog("geyser.core.load", NAME, VERSION));
logger.info("");
+ if (IS_DEV) {
+ // TODO cloud use language string
+ //logger.info(GeyserLocale.getLocaleStringLog("geyser.core.dev_build", "https://discord.gg/geysermc"));
+ logger.info("You are running a development build of Geyser! Please report any bugs you find on our Discord server: %s".formatted("https://discord.gg/geysermc"));
+ logger.info("");
+ }
logger.info("******************************************");
/* Initialize registries */
Registries.init();
BlockRegistries.init();
+ RegistryCache.init();
+
/* Initialize translators */
EntityDefinitions.init();
MessageTranslator.init();
@@ -383,7 +394,7 @@ public class GeyserImpl implements GeyserApi {
this.newsHandler = new NewsHandler(BRANCH, this.buildNumber());
- //Packets.initGeyser();
+ Packets.initGeyser();
if (Epoll.isAvailable()) {
this.erosionUnixListener = new UnixSocketClientListener();
@@ -680,6 +691,7 @@ public class GeyserImpl implements GeyserApi {
*
* @return true if the version number is not 'DEV'.
*/
+ @SuppressWarnings("BooleanMethodIsAlwaysInverted")
public boolean isProductionEnvironment() {
// First is if Blossom runs, second is if Blossom doesn't run
//noinspection ConstantConditions,MismatchedStringCase - changes in production
@@ -766,6 +778,7 @@ public class GeyserImpl implements GeyserApi {
return 0;
}
+ //noinspection DataFlowIssue
return Integer.parseInt(BUILD_NUMBER);
}
diff --git a/core/src/main/java/org/geysermc/geyser/command/defaults/VersionCommand.java b/core/src/main/java/org/geysermc/geyser/command/defaults/VersionCommand.java
index eb2e8ff47..c6852d577 100644
--- a/core/src/main/java/org/geysermc/geyser/command/defaults/VersionCommand.java
+++ b/core/src/main/java/org/geysermc/geyser/command/defaults/VersionCommand.java
@@ -25,8 +25,8 @@
package org.geysermc.geyser.command.defaults;
+import com.fasterxml.jackson.databind.JsonNode;
import org.cloudburstmc.protocol.bedrock.codec.BedrockCodec;
-import org.geysermc.geyser.Constants;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.api.util.PlatformType;
import org.geysermc.geyser.command.GeyserCommand;
@@ -37,8 +37,7 @@ import org.geysermc.geyser.text.ChatColor;
import org.geysermc.geyser.text.GeyserLocale;
import org.geysermc.geyser.util.WebUtils;
-import java.net.URLEncoder;
-import java.nio.charset.StandardCharsets;
+import java.io.IOException;
import java.util.List;
public class VersionCommand extends GeyserCommand {
@@ -72,27 +71,36 @@ public class VersionCommand extends GeyserCommand {
GeyserImpl.NAME, GeyserImpl.VERSION, javaVersions, bedrockVersions));
// Disable update checking in dev mode and for players in Geyser Standalone
- if (GeyserImpl.getInstance().isProductionEnvironment() && !(!sender.isConsole() && geyser.getPlatformType() == PlatformType.STANDALONE)) {
- sender.sendMessage(GeyserLocale.getPlayerLocaleString("geyser.commands.version.checking", sender.locale()));
- try {
- String buildXML = WebUtils.getBody("https://ci.opencollab.dev/job/GeyserMC/job/Geyser/job/" +
- URLEncoder.encode(GeyserImpl.BRANCH, StandardCharsets.UTF_8) + "/lastSuccessfulBuild/api/xml?xpath=//buildNumber");
- if (buildXML.startsWith("")) {
- int latestBuildNum = Integer.parseInt(buildXML.replaceAll("<(\\\\)?(/)?buildNumber>", "").trim());
- int buildNum = this.geyser.buildNumber();
- if (latestBuildNum == buildNum) {
- sender.sendMessage(GeyserLocale.getPlayerLocaleString("geyser.commands.version.no_updates", sender.locale()));
- } else {
- sender.sendMessage(GeyserLocale.getPlayerLocaleString("geyser.commands.version.outdated",
- sender.locale(), (latestBuildNum - buildNum), Constants.GEYSER_DOWNLOAD_LOCATION));
- }
- } else {
- throw new AssertionError("buildNumber missing");
- }
- } catch (Exception e) {
- GeyserImpl.getInstance().getLogger().error(GeyserLocale.getLocaleStringLog("geyser.commands.version.failed"), e);
- sender.sendMessage(ChatColor.RED + GeyserLocale.getPlayerLocaleString("geyser.commands.version.failed", sender.locale()));
+ if (!GeyserImpl.getInstance().isProductionEnvironment() || (!sender.isConsole() && geyser.getPlatformType() == PlatformType.STANDALONE)) {
+ return;
+ }
+
+ if (GeyserImpl.IS_DEV) {
+ // TODO cloud use language string
+ sender.sendMessage("You are running a development build of Geyser! Please report any bugs you find on our Discord server: %s"
+ .formatted("https://discord.gg/geysermc"));
+ //sender.sendMessage(GeyserLocale.getPlayerLocaleString("geyser.core.dev_build", sender.locale(), "https://discord.gg/geysermc"));
+ return;
+ }
+
+ sender.sendMessage(GeyserLocale.getPlayerLocaleString("geyser.commands.version.checking", sender.locale()));
+ try {
+ int buildNumber = this.geyser.buildNumber();
+ JsonNode response = WebUtils.getJson("https://download.geysermc.org/v2/projects/geyser/versions/latest/builds/latest");
+ int latestBuildNumber = response.get("build").asInt();
+
+ if (latestBuildNumber == buildNumber) {
+ sender.sendMessage(GeyserLocale.getPlayerLocaleString("geyser.commands.version.no_updates", sender.locale()));
+ return;
}
+
+ sender.sendMessage(GeyserLocale.getPlayerLocaleString(
+ "geyser.commands.version.outdated",
+ sender.locale(), (latestBuildNumber - buildNumber), "https://geysermc.org/download"
+ ));
+ } catch (IOException e) {
+ GeyserImpl.getInstance().getLogger().error(GeyserLocale.getLocaleStringLog("geyser.commands.version.failed"), e);
+ sender.sendMessage(ChatColor.RED + GeyserLocale.getPlayerLocaleString("geyser.commands.version.failed", sender.locale()));
}
}
diff --git a/core/src/main/java/org/geysermc/geyser/configuration/GeyserConfiguration.java b/core/src/main/java/org/geysermc/geyser/configuration/GeyserConfiguration.java
index d12ab79e9..88bb98171 100644
--- a/core/src/main/java/org/geysermc/geyser/configuration/GeyserConfiguration.java
+++ b/core/src/main/java/org/geysermc/geyser/configuration/GeyserConfiguration.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
+ * Copyright (c) 2019-2024 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
@@ -72,8 +72,10 @@ public interface GeyserConfiguration {
boolean isDebugMode();
+ @Deprecated
boolean isAllowThirdPartyCapes();
+ @Deprecated
boolean isAllowThirdPartyEars();
String getShowCooldown();
diff --git a/core/src/main/java/org/geysermc/geyser/configuration/GeyserJacksonConfiguration.java b/core/src/main/java/org/geysermc/geyser/configuration/GeyserJacksonConfiguration.java
index a55e4af8f..81ac824e4 100644
--- a/core/src/main/java/org/geysermc/geyser/configuration/GeyserJacksonConfiguration.java
+++ b/core/src/main/java/org/geysermc/geyser/configuration/GeyserJacksonConfiguration.java
@@ -94,7 +94,7 @@ public abstract class GeyserJacksonConfiguration implements GeyserConfiguration
private boolean debugMode = false;
@JsonProperty("allow-third-party-capes")
- private boolean allowThirdPartyCapes = true;
+ private boolean allowThirdPartyCapes = false;
@JsonProperty("show-cooldown")
private String showCooldown = "title";
diff --git a/core/src/main/java/org/geysermc/geyser/entity/EntityDefinition.java b/core/src/main/java/org/geysermc/geyser/entity/EntityDefinition.java
index 31aa7cc73..f9b65a545 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/EntityDefinition.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/EntityDefinition.java
@@ -47,6 +47,7 @@ import java.util.function.BiConsumer;
* metadata translators needed to translate the properties sent from the server. The translators are structured in such
* a way that inserting a new one (for example in version updates) is convenient.
*
+ * @param identifier the Bedrock identifier of this entity
* @param the entity type this definition represents
*/
public record EntityDefinition(EntityFactory factory, EntityType entityType, String identifier,
diff --git a/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java b/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java
index 3f2f35305..11b4a32d1 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java
@@ -25,6 +25,9 @@
package org.geysermc.geyser.entity;
+import org.geysermc.geyser.entity.type.AbstractWindChargeEntity;
+import org.geysermc.geyser.entity.factory.EntityFactory;
+import org.geysermc.geyser.entity.type.living.monster.raid.RavagerEntity;
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.MetadataType;
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.FloatEntityMetadata;
@@ -62,6 +65,9 @@ public final class EntityDefinitions {
public static final EntityDefinition BEE;
public static final EntityDefinition BLAZE;
public static final EntityDefinition BOAT;
+ public static final EntityDefinition BOGGED;
+ public static final EntityDefinition BREEZE;
+ public static final EntityDefinition BREEZE_WIND_CHARGE;
public static final EntityDefinition CAMEL;
public static final EntityDefinition CAT;
public static final EntityDefinition CAVE_SPIDER;
@@ -132,7 +138,7 @@ public final class EntityDefinitions {
public static final EntityDefinition POTION;
public static final EntityDefinition PUFFERFISH;
public static final EntityDefinition RABBIT;
- public static final EntityDefinition RAVAGER;
+ public static final EntityDefinition RAVAGER;
public static final EntityDefinition SALMON;
public static final EntityDefinition SHEEP;
public static final EntityDefinition SHULKER;
@@ -164,6 +170,7 @@ public final class EntityDefinitions {
public static final EntityDefinition VINDICATOR;
public static final EntityDefinition WANDERING_TRADER;
public static final EntityDefinition WARDEN;
+ public static final EntityDefinition WIND_CHARGE;
public static final EntityDefinition WITCH;
public static final EntityDefinition WITHER;
public static final EntityDefinition WITHER_SKELETON;
@@ -234,7 +241,7 @@ public final class EntityDefinitions {
.addTranslator(MetadataType.BOOLEAN,
(enderCrystalEntity, entityMetadata) -> enderCrystalEntity.setFlag(EntityFlag.SHOW_BOTTOM, ((BooleanEntityMetadata) entityMetadata).getPrimitiveValue())) // There is a base located on the ender crystal
.build();
- EXPERIENCE_ORB = EntityDefinition.inherited(null, entityBase)
+ EXPERIENCE_ORB = EntityDefinition.inherited(ExpOrbEntity::new, entityBase)
.type(EntityType.EXPERIENCE_ORB)
.identifier("minecraft:xp_orb")
.build();
@@ -296,6 +303,7 @@ public final class EntityDefinitions {
TNT = EntityDefinition.inherited(TNTEntity::new, entityBase)
.type(EntityType.TNT)
.heightAndWidth(0.98f)
+ .offset(0.49f)
.addTranslator(MetadataType.INT, TNTEntity::setFuseLength)
.build();
@@ -373,6 +381,18 @@ public final class EntityDefinitions {
.heightAndWidth(0.25f)
.build();
+ EntityFactory windChargeSupplier = AbstractWindChargeEntity::new;
+ BREEZE_WIND_CHARGE = EntityDefinition.inherited(windChargeSupplier, entityBase)
+ .type(EntityType.BREEZE_WIND_CHARGE)
+ .identifier("minecraft:breeze_wind_charge_projectile")
+ .heightAndWidth(0.3125f)
+ .build();
+ WIND_CHARGE = EntityDefinition.inherited(windChargeSupplier, entityBase)
+ .type(EntityType.WIND_CHARGE)
+ .identifier("minecraft:wind_charge_projectile")
+ .heightAndWidth(0.3125f)
+ .build();
+
EntityDefinition abstractArrowBase = EntityDefinition.inherited(AbstractArrowEntity::new, entityBase)
.addTranslator(MetadataType.BYTE, AbstractArrowEntity::setArrowFlags)
.addTranslator(null) // "Piercing level"
@@ -501,11 +521,20 @@ public final class EntityDefinitions {
.height(0.9f).width(0.5f)
.addTranslator(MetadataType.BYTE, BatEntity::setBatFlags)
.build();
+ BOGGED = EntityDefinition.inherited(BoggedEntity::new, mobEntityBase)
+ .type(EntityType.BOGGED)
+ .height(1.99f).width(0.6f)
+ .addTranslator(MetadataType.BOOLEAN, BoggedEntity::setSheared)
+ .build();
BLAZE = EntityDefinition.inherited(BlazeEntity::new, mobEntityBase)
.type(EntityType.BLAZE)
.height(1.8f).width(0.6f)
.addTranslator(MetadataType.BYTE, BlazeEntity::setBlazeFlags)
.build();
+ BREEZE = EntityDefinition.inherited(BreezeEntity::new, mobEntityBase)
+ .type(EntityType.BREEZE)
+ .height(1.77f).width(0.6f)
+ .build();
CREEPER = EntityDefinition.inherited(CreeperEntity::new, mobEntityBase)
.type(EntityType.CREEPER)
.height(1.7f).width(0.6f)
@@ -745,9 +774,9 @@ public final class EntityDefinitions {
.type(EntityType.PILLAGER)
.height(1.8f).width(0.6f)
.offset(1.62f)
- .addTranslator(null) // Charging; doesn't have an equivalent on Bedrock //TODO check
+ .addTranslator(MetadataType.BOOLEAN, PillagerEntity::setChargingCrossbow)
.build();
- RAVAGER = EntityDefinition.inherited(raidParticipantEntityBase.factory(), raidParticipantEntityBase)
+ RAVAGER = EntityDefinition.inherited(RavagerEntity::new, raidParticipantEntityBase)
.type(EntityType.RAVAGER)
.height(1.9f).width(1.2f)
.build();
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/AbstractWindChargeEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/AbstractWindChargeEntity.java
new file mode 100644
index 000000000..5678c3af4
--- /dev/null
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/AbstractWindChargeEntity.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2024 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.type;
+
+import org.cloudburstmc.math.vector.Vector3f;
+import org.geysermc.geyser.entity.EntityDefinition;
+import org.geysermc.geyser.session.GeyserSession;
+
+import java.util.UUID;
+
+/**
+ * Note that, as of 1.21, a wind charge entity does not actually implement the thrown item. We're just reusing
+ * the "hide until far away" aspect.
+ */
+public class AbstractWindChargeEntity extends ThrowableItemEntity {
+ public AbstractWindChargeEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+ super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
+ }
+
+ @Override
+ public void tick() {
+ super.tick();
+ }
+
+ @Override
+ protected float getDrag() {
+ // Always, even in water. As of 1.21.
+ return 1f;
+ }
+}
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/ArrowEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/ArrowEntity.java
index 1ee706811..ba1241434 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/ArrowEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/ArrowEntity.java
@@ -28,7 +28,7 @@ package org.geysermc.geyser.entity.type;
import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
import org.geysermc.geyser.entity.EntityDefinition;
-import org.geysermc.geyser.inventory.item.TippedArrowPotion;
+import org.geysermc.geyser.inventory.item.Potion;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.IntEntityMetadata;
@@ -46,12 +46,7 @@ public class ArrowEntity extends AbstractArrowEntity {
if (potionColor == -1) {
dirtyMetadata.put(EntityDataTypes.CUSTOM_DISPLAY, (byte) 0);
} else {
- TippedArrowPotion potion = TippedArrowPotion.getByJavaColor(potionColor);
- if (potion != null && potion.getJavaColor() != -1) {
- dirtyMetadata.put(EntityDataTypes.CUSTOM_DISPLAY, (byte) potion.getBedrockId());
- } else {
- dirtyMetadata.put(EntityDataTypes.CUSTOM_DISPLAY, (byte) 0);
- }
+ dirtyMetadata.put(EntityDataTypes.CUSTOM_DISPLAY, Potion.toTippedArrowId(potionColor));
}
}
}
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/BoatEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/BoatEntity.java
index d9a64ccc6..47ae6777a 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/BoatEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/BoatEntity.java
@@ -41,7 +41,7 @@ import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand;
import java.util.UUID;
-public class BoatEntity extends Entity implements Tickable {
+public class BoatEntity extends Entity implements Leashable, Tickable {
/**
* Required when IS_BUOYANT is sent in order for boats to work in the water.
@@ -65,6 +65,8 @@ public class BoatEntity extends Entity implements Tickable {
@Getter
private int variant;
+ private long leashHolderBedrockId = -1;
+
// Looks too fast and too choppy with 0.1f, which is how I believe the Microsoftian client handles it
private final float ROWING_SPEED = 0.1f;
@@ -147,8 +149,18 @@ public class BoatEntity extends Entity implements Tickable {
}
}
+ @Override
+ public void setLeashHolderBedrockId(long bedrockId) {
+ this.leashHolderBedrockId = bedrockId;
+ dirtyMetadata.put(EntityDataTypes.LEASH_HOLDER, bedrockId);
+ }
+
@Override
protected InteractiveTag testInteraction(Hand hand) {
+ InteractiveTag tag = super.testInteraction(hand);
+ if (tag != InteractiveTag.NONE) {
+ return tag;
+ }
if (session.isSneaking()) {
return InteractiveTag.NONE;
} else if (passengers.size() < 2) {
@@ -160,6 +172,10 @@ public class BoatEntity extends Entity implements Tickable {
@Override
public InteractionResult interact(Hand hand) {
+ InteractionResult result = super.interact(hand);
+ if (result != InteractionResult.PASS) {
+ return result;
+ }
if (session.isSneaking()) {
return InteractionResult.PASS;
} else {
@@ -191,6 +207,11 @@ public class BoatEntity extends Entity implements Tickable {
}
}
+ @Override
+ public long leashHolderBedrockId() {
+ return leashHolderBedrockId;
+ }
+
private void sendAnimationPacket(GeyserSession session, Entity rower, AnimatePacket.Action action, float rowTime) {
AnimatePacket packet = new AnimatePacket();
packet.setRuntimeEntityId(rower.getGeyserId());
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/Entity.java b/core/src/main/java/org/geysermc/geyser/entity/type/Entity.java
index fecd72f67..08e87dc03 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/Entity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/Entity.java
@@ -40,6 +40,7 @@ import org.geysermc.geyser.api.entity.type.GeyserEntity;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.entity.GeyserDirtyMetadata;
import org.geysermc.geyser.entity.properties.GeyserEntityPropertyManager;
+import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.text.MessageTranslator;
import org.geysermc.geyser.util.EntityUtils;
@@ -59,6 +60,9 @@ import java.util.*;
@Getter
@Setter
public class Entity implements GeyserEntity {
+
+ private static final boolean PRINT_ENTITY_SPAWN_DEBUG = Boolean.parseBoolean(System.getProperty("Geyser.PrintEntitySpawnDebug", "false"));
+
protected final GeyserSession session;
protected int entityId;
@@ -134,7 +138,7 @@ public class Entity implements GeyserEntity {
this.valid = false;
- this.propertyManager = new GeyserEntityPropertyManager(definition.registeredProperties());
+ this.propertyManager = definition.registeredProperties() == null ? null : new GeyserEntityPropertyManager(definition.registeredProperties());
setPosition(position);
setAirSupply(getMaxAir());
@@ -181,7 +185,7 @@ public class Entity implements GeyserEntity {
flagsDirty = false;
- if (session.getGeyser().getConfig().isDebugMode()) {
+ if (session.getGeyser().getConfig().isDebugMode() && PRINT_ENTITY_SPAWN_DEBUG) {
EntityType type = definition.entityType();
String name = type != null ? type.name() : getClass().getSimpleName();
session.getGeyser().getLogger().debug("Spawned entity " + name + " at location " + position + " with id " + geyserId + " (java id " + entityId + ")");
@@ -361,7 +365,7 @@ public class Entity implements GeyserEntity {
return;
}
- if (propertyManager.hasProperties()) {
+ if (propertyManager != null && propertyManager.hasProperties()) {
SetEntityDataPacket entityDataPacket = new SetEntityDataPacket();
entityDataPacket.setRuntimeEntityId(geyserId);
propertyManager.applyIntProperties(entityDataPacket.getProperties().getIntProperties());
@@ -554,6 +558,17 @@ public class Entity implements GeyserEntity {
* Should usually mirror {@link #interact(Hand)} without any side effects.
*/
protected InteractiveTag testInteraction(Hand hand) {
+ if (isAlive() && this instanceof Leashable leashable) {
+ if (leashable.leashHolderBedrockId() == session.getPlayerEntity().getGeyserId()) {
+ // Note this might be client side. Has yet to be an issue though, as of Java 1.21.
+ return InteractiveTag.REMOVE_LEASH;
+ }
+ if (session.getPlayerInventory().getItemInHand(hand).asItem() == Items.LEAD && leashable.canBeLeashed()) {
+ // We shall leash
+ return InteractiveTag.LEASH;
+ }
+ }
+
return InteractiveTag.NONE;
}
@@ -562,6 +577,18 @@ public class Entity implements GeyserEntity {
* to ensure packet parity as well as functionality parity (such as sound effect responses).
*/
public InteractionResult interact(Hand hand) {
+ if (isAlive() && this instanceof Leashable leashable) {
+ if (leashable.leashHolderBedrockId() == session.getPlayerEntity().getGeyserId()) {
+ // Note this might also update client side (a theoretical Geyser/client desync and Java parity issue).
+ // Has yet to be an issue though, as of Java 1.21.
+ return InteractionResult.SUCCESS;
+ }
+ if (session.getPlayerInventory().getItemInHand(hand).asItem() == Items.LEAD && leashable.canBeLeashed()) {
+ // We shall leash
+ return InteractionResult.SUCCESS;
+ }
+ }
+
return InteractionResult.PASS;
}
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/ExpOrbEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/ExpOrbEntity.java
index 5a79a98b3..9f61bc961 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/ExpOrbEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/ExpOrbEntity.java
@@ -27,11 +27,18 @@ package org.geysermc.geyser.entity.type;
import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
+import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.entity.EntityDefinitions;
import org.geysermc.geyser.session.GeyserSession;
+import java.util.UUID;
+
public class ExpOrbEntity extends Entity {
+ public ExpOrbEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition> entityDefinition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+ this(session, 1, entityId, geyserId, position);
+ }
+
public ExpOrbEntity(GeyserSession session, int amount, int entityId, long geyserId, Vector3f position) {
super(session, entityId, geyserId, null, EntityDefinitions.EXPERIENCE_ORB, position, Vector3f.ZERO, 0, 0, 0);
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/FishingHookEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/FishingHookEntity.java
index f4c0cea36..26a64bcae 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/FishingHookEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/FishingHookEntity.java
@@ -33,6 +33,7 @@ import org.geysermc.erosion.util.BlockPositionIterator;
import org.geysermc.geyser.entity.EntityDefinitions;
import org.geysermc.geyser.entity.type.player.PlayerEntity;
import org.geysermc.geyser.level.block.BlockStateValues;
+import org.geysermc.geyser.level.block.type.Block;
import org.geysermc.geyser.level.physics.BoundingBox;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.collision.BlockCollision;
@@ -162,7 +163,7 @@ public class FishingHookEntity extends ThrowableEntity {
*/
protected boolean isInAir() {
int block = session.getGeyser().getWorldManager().getBlockAt(session, position.toInt());
- return block == BlockStateValues.JAVA_AIR_ID;
+ return block == Block.JAVA_AIR_ID;
}
@Override
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/FurnaceMinecartEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/FurnaceMinecartEntity.java
index ef584c4fd..e33e6d7b6 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/FurnaceMinecartEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/FurnaceMinecartEntity.java
@@ -25,14 +25,16 @@
package org.geysermc.geyser.entity.type;
-import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
-import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand;
import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
import org.geysermc.geyser.entity.EntityDefinition;
-import org.geysermc.geyser.level.block.BlockStateValues;
+import org.geysermc.geyser.level.block.Blocks;
+import org.geysermc.geyser.level.block.property.Properties;
+import org.geysermc.geyser.level.block.type.BlockState;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.util.InteractionResult;
+import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
+import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand;
import java.util.UUID;
@@ -51,7 +53,8 @@ public class FurnaceMinecartEntity extends DefaultBlockMinecartEntity {
@Override
public void updateDefaultBlockMetadata() {
- dirtyMetadata.put(EntityDataTypes.DISPLAY_BLOCK_STATE, session.getBlockMappings().getBedrockBlock(hasFuel ? BlockStateValues.JAVA_FURNACE_LIT_ID : BlockStateValues.JAVA_FURNACE_ID));
+ BlockState furnace = Blocks.FURNACE.defaultBlockState().withValue(Properties.LIT, hasFuel);
+ dirtyMetadata.put(EntityDataTypes.DISPLAY_BLOCK_STATE, session.getBlockMappings().getBedrockBlock(furnace));
dirtyMetadata.put(EntityDataTypes.DISPLAY_OFFSET, 6);
}
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/InteractionEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/InteractionEntity.java
index 4e7a805b4..06035a47c 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/InteractionEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/InteractionEntity.java
@@ -80,7 +80,10 @@ public class InteractionEntity extends Entity {
}
public void setHeight(FloatEntityMetadata height) {
- setBoundingBoxHeight(height.getPrimitiveValue());
+ // Bedrock does *not* like high values being placed here
+ // https://gist.github.com/Owen1212055/f5d59169d3a6a5c32f0c173d57eb199d recommend(s/ed) using the tactic
+ // https://github.com/GeyserMC/Geyser/issues/4688
+ setBoundingBoxHeight(Math.min(height.getPrimitiveValue(), 64f));
}
public void setResponse(BooleanEntityMetadata response) {
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/ItemEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/ItemEntity.java
index ead717b34..49eb9ddc4 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/ItemEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/ItemEntity.java
@@ -34,6 +34,7 @@ import org.cloudburstmc.protocol.bedrock.packet.AddItemEntityPacket;
import org.cloudburstmc.protocol.bedrock.packet.EntityEventPacket;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.level.block.BlockStateValues;
+import org.geysermc.geyser.level.block.type.BlockState;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.item.ItemTranslator;
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.EntityMetadata;
@@ -137,7 +138,7 @@ public class ItemEntity extends ThrowableEntity {
protected float getDrag() {
if (isOnGround()) {
Vector3i groundBlockPos = position.toInt().down(1);
- int blockState = session.getGeyser().getWorldManager().getBlockAt(session, groundBlockPos);
+ BlockState blockState = session.getGeyser().getWorldManager().blockAt(session, groundBlockPos);
return BlockStateValues.getSlipperiness(blockState) * 0.98f;
}
return 0.98f;
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/Leashable.java b/core/src/main/java/org/geysermc/geyser/entity/type/Leashable.java
new file mode 100644
index 000000000..64d95ba3c
--- /dev/null
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/Leashable.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2024 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.type;
+
+/**
+ * I can haz lead
+ * (The item, not the mineral)
+ */
+public interface Leashable {
+ void setLeashHolderBedrockId(long bedrockId);
+
+ long leashHolderBedrockId();
+
+ default boolean canBeLeashed() {
+ return isNotLeashed();
+ }
+
+ default boolean isNotLeashed() {
+ return leashHolderBedrockId() == -1L;
+ }
+}
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/LivingEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/LivingEntity.java
index d27fa3cad..499084555 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/LivingEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/LivingEntity.java
@@ -352,6 +352,15 @@ public class LivingEntity extends Entity {
session.sendUpstreamPacket(offHandPacket);
}
+ /**
+ * Called when a SWING_ARM animation packet is received
+ *
+ * @return true if an ATTACK_START event should be used instead
+ */
+ public boolean useArmSwingAttack() {
+ return false;
+ }
+
/**
* Attributes are properties of an entity that are generally more runtime-based instead of permanent properties.
* Movement speed, current attack damage with a weapon, current knockback resistance.
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/PaintingEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/PaintingEntity.java
index f5145c11f..09c055c84 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/PaintingEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/PaintingEntity.java
@@ -30,6 +30,8 @@ import org.cloudburstmc.protocol.bedrock.packet.AddPaintingPacket;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.level.PaintingType;
import org.geysermc.geyser.session.GeyserSession;
+import org.geysermc.mcprotocollib.protocol.data.game.Holder;
+import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.PaintingVariant;
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ObjectEntityMetadata;
import org.geysermc.mcprotocollib.protocol.data.game.entity.object.Direction;
@@ -49,8 +51,14 @@ public class PaintingEntity extends Entity {
// Wait until we get the metadata needed
}
- public void setPaintingType(ObjectEntityMetadata entityMetadata) {
- PaintingType type = PaintingType.getByPaintingType(entityMetadata.getValue());
+ public void setPaintingType(ObjectEntityMetadata> entityMetadata) {
+ if (!entityMetadata.getValue().isId()) {
+ return;
+ }
+ PaintingType type = session.getRegistryCache().paintings().byId(entityMetadata.getValue().id());
+ if (type == null) {
+ return;
+ }
AddPaintingPacket addPaintingPacket = new AddPaintingPacket();
addPaintingPacket.setUniqueEntityId(geyserId);
addPaintingPacket.setRuntimeEntityId(geyserId);
@@ -78,8 +86,12 @@ public class PaintingEntity extends Entity {
private Vector3f fixOffset(PaintingType paintingName) {
Vector3f position = super.position;
- position = position.add(0.5, 0.5, 0.5);
- double widthOffset = paintingName.getWidth() > 1 ? 0.5 : 0;
+ // ViaVersion already adds the offset for us on older versions,
+ // so no need to do it then otherwise it will be spaced
+ if (session.isEmulatePost1_18Logic()) {
+ position = position.add(0.5, 0.5, 0.5);
+ }
+ double widthOffset = paintingName.getWidth() > 1 && paintingName.getWidth() != 3 ? 0.5 : 0;
double heightOffset = paintingName.getHeight() > 1 && paintingName.getHeight() != 3 ? 0.5 : 0;
return switch (direction) {
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/SpawnerMinecartEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/SpawnerMinecartEntity.java
index 49cfc0081..4d69c8a1e 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/SpawnerMinecartEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/SpawnerMinecartEntity.java
@@ -28,7 +28,7 @@ package org.geysermc.geyser.entity.type;
import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
import org.geysermc.geyser.entity.EntityDefinition;
-import org.geysermc.geyser.level.block.BlockStateValues;
+import org.geysermc.geyser.level.block.Blocks;
import org.geysermc.geyser.session.GeyserSession;
import java.util.UUID;
@@ -41,7 +41,7 @@ public class SpawnerMinecartEntity extends DefaultBlockMinecartEntity {
@Override
public void updateDefaultBlockMetadata() {
- dirtyMetadata.put(EntityDataTypes.DISPLAY_BLOCK_STATE, session.getBlockMappings().getBedrockBlock(BlockStateValues.JAVA_SPAWNER_ID));
+ dirtyMetadata.put(EntityDataTypes.DISPLAY_BLOCK_STATE, session.getBlockMappings().getBedrockBlock(Blocks.SPAWNER.defaultBlockState()));
dirtyMetadata.put(EntityDataTypes.DISPLAY_OFFSET, 6);
}
}
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/TNTEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/TNTEntity.java
index dca36cda0..47d97b8f7 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/TNTEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/TNTEntity.java
@@ -39,7 +39,17 @@ public class TNTEntity extends Entity implements Tickable {
private int currentTick;
public TNTEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
- super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
+ super(session, entityId, geyserId, uuid, definition, position.add(0, definition.offset(), 0), motion, yaw, pitch, headYaw);
+ }
+
+ @Override
+ public void moveRelative(double relX, double relY, double relZ, float yaw, float pitch, boolean isOnGround) {
+ super.moveRelative(relX, relY + definition.offset(), relZ, yaw, pitch, isOnGround);
+ }
+
+ @Override
+ public void moveAbsolute(Vector3f position, float yaw, float pitch, float headYaw, boolean isOnGround, boolean teleported) {
+ super.moveAbsolute(position.add(Vector3f.from(0, definition.offset(), 0)), yaw, pitch, headYaw, isOnGround, teleported);
}
public void setFuseLength(IntEntityMetadata entityMetadata) {
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/AmbientEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/AmbientEntity.java
index 8f81125d0..f4b80edf1 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/AmbientEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/AmbientEntity.java
@@ -38,7 +38,7 @@ public class AmbientEntity extends MobEntity {
}
@Override
- protected boolean canBeLeashed() {
+ public boolean canBeLeashed() {
return false;
}
}
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/DolphinEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/DolphinEntity.java
index 6182a27f4..a0ea79d67 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/DolphinEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/DolphinEntity.java
@@ -43,7 +43,7 @@ public class DolphinEntity extends WaterEntity {
}
@Override
- protected boolean canBeLeashed() {
+ public boolean canBeLeashed() {
return true;
}
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/MobEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/MobEntity.java
index 95145ae60..9accf178f 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/MobEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/MobEntity.java
@@ -25,12 +25,12 @@
package org.geysermc.geyser.entity.type.living;
-import lombok.Getter;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.entity.EntityDefinition;
+import org.geysermc.geyser.entity.type.Leashable;
import org.geysermc.geyser.entity.type.LivingEntity;
import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.item.Items;
@@ -43,11 +43,10 @@ import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand;
import java.util.UUID;
-public class MobEntity extends LivingEntity {
+public class MobEntity extends LivingEntity implements Leashable {
/**
* If another mob is holding this mob by a leash, this variable tracks their Bedrock entity ID.
*/
- @Getter
private long leashHolderBedrockId;
public MobEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
@@ -65,6 +64,7 @@ public class MobEntity extends LivingEntity {
setFlag(EntityFlag.NO_AI, (xd & 0x01) == 0x01);
}
+ @Override
public void setLeashHolderBedrockId(long bedrockId) {
this.leashHolderBedrockId = bedrockId;
dirtyMetadata.put(EntityDataTypes.LEASH_HOLDER, bedrockId);
@@ -79,10 +79,7 @@ public class MobEntity extends LivingEntity {
return InteractiveTag.REMOVE_LEASH;
} else {
GeyserItemStack itemStack = session.getPlayerInventory().getItemInHand(hand);
- if (itemStack.asItem() == Items.LEAD && canBeLeashed()) {
- // We shall leash
- return InteractiveTag.LEASH;
- } else if (itemStack.asItem() == Items.NAME_TAG) {
+ if (itemStack.asItem() == Items.NAME_TAG) {
InteractionResult result = checkInteractWithNameTag(itemStack);
if (result.consumesAction()) {
return InteractiveTag.NAME;
@@ -99,9 +96,6 @@ public class MobEntity extends LivingEntity {
if (!isAlive()) {
// dead lol
return InteractionResult.PASS;
- } else if (leashHolderBedrockId == session.getPlayerEntity().getGeyserId()) {
- // TODO looks like the client assumes it will go through and removes the attachment itself?
- return InteractionResult.SUCCESS;
} else {
GeyserItemStack itemInHand = session.getPlayerInventory().getItemInHand(hand);
InteractionResult result = checkPriorityInteractions(itemInHand);
@@ -115,10 +109,7 @@ public class MobEntity extends LivingEntity {
}
private InteractionResult checkPriorityInteractions(GeyserItemStack itemInHand) {
- if (itemInHand.asItem() == Items.LEAD && canBeLeashed()) {
- // We shall leash
- return InteractionResult.SUCCESS;
- } else if (itemInHand.asItem() == Items.NAME_TAG) {
+ if (itemInHand.asItem() == Items.NAME_TAG) {
InteractionResult result = checkInteractWithNameTag(itemInHand);
if (result.consumesAction()) {
return result;
@@ -143,12 +134,14 @@ public class MobEntity extends LivingEntity {
return InteractionResult.PASS;
}
- protected boolean canBeLeashed() {
+ @Override
+ public boolean canBeLeashed() {
return isNotLeashed() && !isEnemy();
}
- protected final boolean isNotLeashed() {
- return leashHolderBedrockId == -1L;
+ @Override
+ public long leashHolderBedrockId() {
+ return leashHolderBedrockId;
}
/**
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/SquidEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/SquidEntity.java
index 80a5af442..6285bd9a4 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/SquidEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/SquidEntity.java
@@ -122,7 +122,7 @@ public class SquidEntity extends WaterEntity implements Tickable {
}
@Override
- protected boolean canBeLeashed() {
+ public boolean canBeLeashed() {
return isNotLeashed();
}
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/WaterEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/WaterEntity.java
index a847c4cd7..ae9d0d659 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/WaterEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/WaterEntity.java
@@ -38,7 +38,7 @@ public class WaterEntity extends CreatureEntity {
}
@Override
- protected boolean canBeLeashed() {
+ public boolean canBeLeashed() {
return false;
}
}
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/AxolotlEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/AxolotlEntity.java
index a87b1dd5e..a0ab56ead 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/AxolotlEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/AxolotlEntity.java
@@ -72,7 +72,7 @@ public class AxolotlEntity extends AnimalEntity {
}
@Override
- protected boolean canBeLeashed() {
+ public boolean canBeLeashed() {
return true;
}
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/HoglinEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/HoglinEntity.java
index 46cafad02..cc23fc607 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/HoglinEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/HoglinEntity.java
@@ -27,6 +27,7 @@ package org.geysermc.geyser.entity.type.living.animal;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.cloudburstmc.math.vector.Vector3f;
+import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.session.GeyserSession;
@@ -40,6 +41,8 @@ public class HoglinEntity extends AnimalEntity {
public HoglinEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
+ dirtyMetadata.put(EntityDataTypes.TARGET_EID, session.getPlayerEntity().getGeyserId());
+ setFlag(EntityFlag.SHAKING, isShaking());
}
public void setImmuneToZombification(BooleanEntityMetadata entityMetadata) {
@@ -60,7 +63,7 @@ public class HoglinEntity extends AnimalEntity {
}
@Override
- protected boolean canBeLeashed() {
+ public boolean canBeLeashed() {
return isNotLeashed();
}
@@ -68,4 +71,9 @@ public class HoglinEntity extends AnimalEntity {
protected boolean isEnemy() {
return true;
}
+
+ @Override
+ public boolean useArmSwingAttack() {
+ return true;
+ }
}
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PandaEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PandaEntity.java
index 79401f63f..aaa7c2d7e 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PandaEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PandaEntity.java
@@ -123,7 +123,7 @@ public class PandaEntity extends AnimalEntity {
}
@Override
- protected boolean canBeLeashed() {
+ public boolean canBeLeashed() {
return false;
}
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/TurtleEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/TurtleEntity.java
index b3c1128e3..16901a844 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/TurtleEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/TurtleEntity.java
@@ -56,7 +56,7 @@ public class TurtleEntity extends AnimalEntity {
}
@Override
- protected boolean canBeLeashed() {
+ public boolean canBeLeashed() {
return false;
}
}
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/TameableEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/TameableEntity.java
index e16823d37..ea347d193 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/TameableEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/TameableEntity.java
@@ -84,7 +84,7 @@ public abstract class TameableEntity extends AnimalEntity {
}
@Override
- protected boolean canBeLeashed() {
+ public boolean canBeLeashed() {
return isNotLeashed();
}
}
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/WolfEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/WolfEntity.java
index 4573f0e7a..e7fde2be8 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/WolfEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/tameable/WolfEntity.java
@@ -33,36 +33,28 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.cloudburstmc.protocol.bedrock.packet.UpdateAttributesPacket;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.inventory.GeyserItemStack;
-import org.geysermc.geyser.inventory.item.Enchantment;
import org.geysermc.geyser.item.Items;
+import org.geysermc.geyser.item.enchantment.EnchantmentComponent;
import org.geysermc.geyser.item.type.DyeItem;
-import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.session.cache.tags.ItemTag;
import org.geysermc.geyser.util.InteractionResult;
import org.geysermc.geyser.util.InteractiveTag;
import org.geysermc.geyser.util.ItemUtils;
+import org.geysermc.mcprotocollib.protocol.data.game.Holder;
+import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.WolfVariant;
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.IntEntityMetadata;
+import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ObjectEntityMetadata;
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode;
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand;
import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack;
import java.util.Collections;
import java.util.Locale;
-import java.util.Set;
import java.util.UUID;
public class WolfEntity extends TameableEntity {
- /**
- * A list of all foods a wolf can eat on Java Edition.
- * Used to display interactive tag or particles if needed.
- * TODO generate
- */
- private static final Set WOLF_FOODS = Set.of(Items.PUFFERFISH, Items.TROPICAL_FISH, Items.CHICKEN, Items.COOKED_CHICKEN,
- Items.PORKCHOP, Items.BEEF, Items.RABBIT, Items.COOKED_PORKCHOP, Items.COOKED_BEEF, Items.ROTTEN_FLESH, Items.MUTTON, Items.COOKED_MUTTON,
- Items.COOKED_RABBIT);
-
private byte collarColor = 14; // Red - default
private boolean isCurseOfBinding = false;
@@ -112,12 +104,14 @@ public class WolfEntity extends TameableEntity {
}
// 1.20.5+
- public void setWolfVariant(IntEntityMetadata entityMetadata) {
- WolfVariant wolfVariant = session.getRegistryCache().wolfVariants().byId(entityMetadata.getPrimitiveValue());
- if (wolfVariant == null) {
- wolfVariant = WolfVariant.PALE;
- }
- dirtyMetadata.put(EntityDataTypes.VARIANT, wolfVariant.ordinal());
+ public void setWolfVariant(ObjectEntityMetadata> entityMetadata) {
+ entityMetadata.getValue().ifId(id -> {
+ BuiltInWolfVariant wolfVariant = session.getRegistryCache().wolfVariants().byId(id);
+ if (wolfVariant == null) {
+ wolfVariant = BuiltInWolfVariant.PALE;
+ }
+ dirtyMetadata.put(EntityDataTypes.VARIANT, wolfVariant.ordinal());
+ });
}
@Override
@@ -129,11 +123,11 @@ public class WolfEntity extends TameableEntity {
@Override
public void setChestplate(ItemStack stack) {
super.setChestplate(stack);
- isCurseOfBinding = ItemUtils.getEnchantmentLevel(stack.getDataComponents(), Enchantment.JavaEnchantment.BINDING_CURSE) > 0;
+ isCurseOfBinding = ItemUtils.hasEffect(session, stack, EnchantmentComponent.PREVENT_ARMOR_CHANGE); // TODO test
}
@Override
- protected boolean canBeLeashed() {
+ public boolean canBeLeashed() {
return !getFlag(EntityFlag.ANGRY) && super.canBeLeashed();
}
@@ -187,7 +181,7 @@ public class WolfEntity extends TameableEntity {
}
// Ordered by bedrock id
- public enum WolfVariant {
+ public enum BuiltInWolfVariant {
PALE,
ASHEN,
BLACK,
@@ -198,16 +192,16 @@ public class WolfEntity extends TameableEntity {
STRIPED,
WOODS;
- private static final WolfVariant[] VALUES = values();
+ private static final BuiltInWolfVariant[] VALUES = values();
private final String javaIdentifier;
- WolfVariant() {
+ BuiltInWolfVariant() {
this.javaIdentifier = "minecraft:" + this.name().toLowerCase(Locale.ROOT);
}
- public static @Nullable WolfVariant getByJavaIdentifier(String javaIdentifier) {
- for (WolfVariant wolfVariant : VALUES) {
+ public static @Nullable BuiltInWolfVariant getByJavaIdentifier(String javaIdentifier) {
+ for (BuiltInWolfVariant wolfVariant : VALUES) {
if (wolfVariant.javaIdentifier.equals(javaIdentifier)) {
return wolfVariant;
}
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/merchant/AbstractMerchantEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/merchant/AbstractMerchantEntity.java
index 64e35e52e..2492aabd7 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/merchant/AbstractMerchantEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/merchant/AbstractMerchantEntity.java
@@ -47,7 +47,7 @@ public class AbstractMerchantEntity extends AgeableEntity {
}
@Override
- protected boolean canBeLeashed() {
+ public boolean canBeLeashed() {
return false;
}
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/merchant/VillagerEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/merchant/VillagerEntity.java
index 3c2160a2b..d7efa9f1d 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/merchant/VillagerEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/merchant/VillagerEntity.java
@@ -33,8 +33,9 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.cloudburstmc.protocol.bedrock.packet.MoveEntityAbsolutePacket;
import org.geysermc.geyser.entity.EntityDefinition;
-import org.geysermc.geyser.registry.BlockRegistries;
-import org.geysermc.geyser.registry.type.BlockMapping;
+import org.geysermc.geyser.level.block.property.Properties;
+import org.geysermc.geyser.level.block.type.BedBlock;
+import org.geysermc.geyser.level.block.type.BlockState;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.EntityMetadata;
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.VillagerData;
@@ -119,28 +120,31 @@ public class VillagerEntity extends AbstractMerchantEntity {
}
// The bed block
- int blockId = session.getGeyser().getWorldManager().getBlockAt(session, bedPosition);
- String fullIdentifier = BlockRegistries.JAVA_BLOCKS.getOrDefault(blockId, BlockMapping.DEFAULT).getJavaIdentifier();
+ BlockState state = session.getGeyser().getWorldManager().blockAt(session, bedPosition);
// Set the correct position offset and rotation when sleeping
int bedRotation = 0;
float xOffset = 0;
float zOffset = 0;
- if (fullIdentifier.contains("facing=south")) {
- // bed is facing south
- bedRotation = 180;
- zOffset = -.5f;
- } else if (fullIdentifier.contains("facing=east")) {
- // bed is facing east
- bedRotation = 90;
- xOffset = -.5f;
- } else if (fullIdentifier.contains("facing=west")) {
- // bed is facing west
- bedRotation = 270;
- xOffset = .5f;
- } else if (fullIdentifier.contains("facing=north")) {
- // rotation does not change because north is 0
- zOffset = .5f;
+ if (state.block() instanceof BedBlock) {
+ switch (state.getValue(Properties.HORIZONTAL_FACING)) {
+ case SOUTH -> {
+ bedRotation = 180;
+ zOffset = -.5f;
+ }
+ case EAST -> {
+ bedRotation = 90;
+ xOffset = -.5f;
+ }
+ case WEST -> {
+ bedRotation = 270;
+ xOffset = .5f;
+ }
+ case NORTH -> {
+ // rotation does not change because north is 0
+ zOffset = .5f;
+ }
+ }
}
setYaw(yaw);
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/AbstractSkeletonEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/AbstractSkeletonEntity.java
index 3fbdda245..d08fff06a 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/AbstractSkeletonEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/AbstractSkeletonEntity.java
@@ -26,7 +26,9 @@
package org.geysermc.geyser.entity.type.living.monster;
import org.cloudburstmc.math.vector.Vector3f;
+import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
+import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
@@ -45,5 +47,17 @@ public class AbstractSkeletonEntity extends MonsterEntity {
byte xd = entityMetadata.getPrimitiveValue();
// A bit of a loophole so the hands get raised - set the target ID to its own ID
dirtyMetadata.put(EntityDataTypes.TARGET_EID, ((xd & 4) == 4) ? geyserId : 0);
+
+ if ((xd & 4) == 4) {
+ ItemDefinition bow = session.getItemMappings().getStoredItems().bow().getBedrockDefinition();
+ setFlag(EntityFlag.FACING_TARGET_TO_RANGE_ATTACK, this.hand.getDefinition() == bow || this.offhand.getDefinition() == bow);
+ } else {
+ setFlag(EntityFlag.FACING_TARGET_TO_RANGE_ATTACK, false);
+ }
+ }
+
+ @Override
+ public boolean useArmSwingAttack() {
+ return true;
}
}
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/BasePiglinEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/BasePiglinEntity.java
index 09bd28cd0..9258cd3b8 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/BasePiglinEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/BasePiglinEntity.java
@@ -26,10 +26,13 @@
package org.geysermc.geyser.entity.type.living.monster;
import org.cloudburstmc.math.vector.Vector3f;
+import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
+import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
+import org.geysermc.mcprotocollib.protocol.data.game.entity.type.EntityType;
import java.util.UUID;
@@ -38,6 +41,16 @@ public class BasePiglinEntity extends MonsterEntity {
public BasePiglinEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
+ // Both TARGET_EID and BLOCK are needed for melee attack animation
+ dirtyMetadata.put(EntityDataTypes.BLOCK, session.getBlockMappings().getDefinition(1));
+ setFlag(EntityFlag.SHAKING, isShaking());
+ }
+
+ @Override
+ public void setMobFlags(ByteEntityMetadata entityMetadata) {
+ super.setMobFlags(entityMetadata);
+ byte xd = entityMetadata.getPrimitiveValue();
+ dirtyMetadata.put(EntityDataTypes.TARGET_EID, (xd & 4) == 4 ? session.getPlayerEntity().getGeyserId() : 0);
}
public void setImmuneToZombification(BooleanEntityMetadata entityMetadata) {
@@ -50,4 +63,9 @@ public class BasePiglinEntity extends MonsterEntity {
protected boolean isShaking() {
return (!isImmuneToZombification && !session.getDimensionType().piglinSafe()) || super.isShaking();
}
+
+ @Override
+ public boolean useArmSwingAttack() {
+ return true;
+ }
}
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/BoggedEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/BoggedEntity.java
new file mode 100644
index 000000000..806d58ed1
--- /dev/null
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/BoggedEntity.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2024 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.type.living.monster;
+
+import org.checkerframework.checker.nullness.qual.NonNull;
+import org.cloudburstmc.math.vector.Vector3f;
+import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
+import org.geysermc.geyser.entity.EntityDefinition;
+import org.geysermc.geyser.inventory.GeyserItemStack;
+import org.geysermc.geyser.item.Items;
+import org.geysermc.geyser.session.GeyserSession;
+import org.geysermc.geyser.util.InteractionResult;
+import org.geysermc.geyser.util.InteractiveTag;
+import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
+import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand;
+
+import java.util.UUID;
+
+public class BoggedEntity extends AbstractSkeletonEntity {
+ private boolean sheared = false;
+
+ public BoggedEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+ super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
+ }
+
+ public void setSheared(BooleanEntityMetadata entityMetadata) {
+ this.sheared = entityMetadata.getPrimitiveValue();
+ setFlag(EntityFlag.SHEARED, this.sheared);
+ }
+
+ @Override
+ protected @NonNull InteractiveTag testMobInteraction(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) {
+ if (itemInHand.asItem() == Items.SHEARS && readyForShearing()) {
+ return InteractiveTag.SHEAR;
+ }
+ return super.testMobInteraction(hand, itemInHand);
+ }
+
+ @Override
+ protected @NonNull InteractionResult mobInteract(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) {
+ if (itemInHand.asItem() == Items.SHEARS && readyForShearing()) {
+ return InteractionResult.SUCCESS;
+ }
+ return super.mobInteract(hand, itemInHand);
+ }
+
+ private boolean readyForShearing() {
+ return !this.sheared && this.isAlive();
+ }
+}
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/BreezeEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/BreezeEntity.java
new file mode 100644
index 000000000..251a77fb9
--- /dev/null
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/BreezeEntity.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2024 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.type.living.monster;
+
+import org.cloudburstmc.math.vector.Vector3f;
+import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
+import org.geysermc.geyser.entity.EntityDefinition;
+import org.geysermc.geyser.session.GeyserSession;
+import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.Pose;
+
+import java.util.UUID;
+
+public class BreezeEntity extends MonsterEntity {
+ public BreezeEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+ super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
+ }
+
+ @Override
+ public void setPose(Pose pose) {
+ // TODO Test
+ setFlag(EntityFlag.FACING_TARGET_TO_RANGE_ATTACK, pose == Pose.SHOOTING);
+ setFlag(EntityFlag.JUMP_GOAL_JUMP, pose == Pose.INHALING);
+ super.setPose(pose);
+ }
+}
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/PiglinEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/PiglinEntity.java
index f0f01272f..19b6d8e69 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/PiglinEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/PiglinEntity.java
@@ -27,16 +27,22 @@ package org.geysermc.geyser.entity.type.living.monster;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.cloudburstmc.math.vector.Vector3f;
+import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
+import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerId;
+import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
+import org.cloudburstmc.protocol.bedrock.packet.MobEquipmentPacket;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.item.Items;
+import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.session.cache.tags.ItemTag;
import org.geysermc.geyser.util.InteractionResult;
import org.geysermc.geyser.util.InteractiveTag;
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand;
+import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack;
import java.util.UUID;
@@ -55,13 +61,61 @@ public class PiglinEntity extends BasePiglinEntity {
}
public void setChargingCrossbow(BooleanEntityMetadata entityMetadata) {
- setFlag(EntityFlag.CHARGING, entityMetadata.getPrimitiveValue());
+ boolean charging = entityMetadata.getPrimitiveValue();
+ setFlag(EntityFlag.CHARGING, charging);
+ dirtyMetadata.put(EntityDataTypes.CHARGE_AMOUNT, charging ? (byte) 64 : (byte) 0); // TODO: gradually increase
}
public void setDancing(BooleanEntityMetadata entityMetadata) {
setFlag(EntityFlag.DANCING, entityMetadata.getPrimitiveValue());
}
+ @Override
+ public void setHand(ItemStack stack) {
+ ItemMapping crossbow = session.getItemMappings().getStoredItems().crossbow();
+ boolean toCrossbow = stack != null && stack.getId() == crossbow.getJavaItem().javaId();
+
+ if (toCrossbow ^ this.hand.getDefinition() == crossbow.getBedrockDefinition()) { // If switching to/from crossbow
+ dirtyMetadata.put(EntityDataTypes.BLOCK, session.getBlockMappings().getDefinition(toCrossbow ? 0 : 1));
+ dirtyMetadata.put(EntityDataTypes.CHARGE_AMOUNT, (byte) 0);
+ setFlag(EntityFlag.CHARGED, false);
+ setFlag(EntityFlag.USING_ITEM, false);
+ updateBedrockMetadata();
+
+ if (this.hand.isValid()) {
+ MobEquipmentPacket mobEquipmentPacket = new MobEquipmentPacket();
+ mobEquipmentPacket.setRuntimeEntityId(geyserId);
+ mobEquipmentPacket.setContainerId(ContainerId.INVENTORY);
+ mobEquipmentPacket.setInventorySlot(0);
+ mobEquipmentPacket.setHotbarSlot(-1);
+ mobEquipmentPacket.setItem(ItemData.AIR);
+ session.sendUpstreamPacket(mobEquipmentPacket);
+ }
+ }
+
+ super.setHand(stack);
+ }
+
+ @Override
+ public void updateMainHand(GeyserSession session) {
+ super.updateMainHand(session);
+
+ if (this.hand.getDefinition() == session.getItemMappings().getStoredItems().crossbow().getBedrockDefinition()) {
+ if (this.hand.getTag() != null && this.hand.getTag().containsKey("chargedItem")) {
+ dirtyMetadata.put(EntityDataTypes.CHARGE_AMOUNT, Byte.MAX_VALUE);
+ setFlag(EntityFlag.CHARGING, false);
+ setFlag(EntityFlag.CHARGED, true);
+ setFlag(EntityFlag.USING_ITEM, true);
+ } else if (getFlag(EntityFlag.CHARGED)) {
+ dirtyMetadata.put(EntityDataTypes.CHARGE_AMOUNT, (byte) 0);
+ setFlag(EntityFlag.CHARGED, false);
+ setFlag(EntityFlag.USING_ITEM, false);
+ }
+ }
+
+ updateBedrockMetadata();
+ }
+
@Override
public void updateOffHand(GeyserSession session) {
// Check if the Piglin is holding Gold and set the ADMIRING flag accordingly so its pose updates
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ZoglinEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ZoglinEntity.java
index 7eb950e21..3d6e381c7 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ZoglinEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ZoglinEntity.java
@@ -26,6 +26,7 @@
package org.geysermc.geyser.entity.type.living.monster;
import org.cloudburstmc.math.vector.Vector3f;
+import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.session.GeyserSession;
@@ -37,6 +38,7 @@ public class ZoglinEntity extends MonsterEntity {
public ZoglinEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
+ dirtyMetadata.put(EntityDataTypes.TARGET_EID, session.getPlayerEntity().getGeyserId());
}
public void setBaby(BooleanEntityMetadata entityMetadata) {
@@ -56,7 +58,7 @@ public class ZoglinEntity extends MonsterEntity {
}
@Override
- protected boolean canBeLeashed() {
+ public boolean canBeLeashed() {
return isNotLeashed();
}
@@ -64,4 +66,9 @@ public class ZoglinEntity extends MonsterEntity {
protected boolean isEnemy() {
return true;
}
+
+ @Override
+ public boolean useArmSwingAttack() {
+ return true;
+ }
}
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ZombieEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ZombieEntity.java
index b8351089d..b07afd742 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ZombieEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ZombieEntity.java
@@ -57,4 +57,9 @@ public class ZombieEntity extends MonsterEntity {
protected boolean isShaking() {
return convertingToDrowned || super.isShaking();
}
+
+ @Override
+ public boolean useArmSwingAttack() {
+ return true;
+ }
}
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/raid/PillagerEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/raid/PillagerEntity.java
index 1d2d9115b..fd7448e29 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/raid/PillagerEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/raid/PillagerEntity.java
@@ -26,10 +26,13 @@
package org.geysermc.geyser.entity.type.living.monster.raid;
import org.cloudburstmc.math.vector.Vector3f;
+import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
+import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.session.GeyserSession;
+import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
import java.util.UUID;
@@ -39,16 +42,22 @@ public class PillagerEntity extends AbstractIllagerEntity {
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
}
+ public void setChargingCrossbow(BooleanEntityMetadata entityMetadata) {
+ boolean charging = entityMetadata.getPrimitiveValue();
+ setFlag(EntityFlag.CHARGING, charging);
+ dirtyMetadata.put(EntityDataTypes.CHARGE_AMOUNT, charging ? (byte) 64 : (byte) 0); // TODO: gradually increase
+ }
+
@Override
- public void updateMainHand(GeyserSession session) { //TODO
- checkForCrossbow();
+ public void updateMainHand(GeyserSession session) {
+ updateCrossbow();
super.updateMainHand(session);
}
@Override
public void updateOffHand(GeyserSession session) {
- checkForCrossbow();
+ updateCrossbow();
super.updateOffHand(session);
}
@@ -56,12 +65,27 @@ public class PillagerEntity extends AbstractIllagerEntity {
/**
* Check for a crossbow in either the mainhand or offhand. If one exists, indicate that the pillager should be posing
*/
- protected void checkForCrossbow() {
+ protected void updateCrossbow() {
ItemMapping crossbow = session.getItemMappings().getStoredItems().crossbow();
- boolean hasCrossbow = this.hand.getDefinition() == crossbow.getBedrockDefinition()
- || this.offhand.getDefinition() == crossbow.getBedrockDefinition();
- setFlag(EntityFlag.USING_ITEM, hasCrossbow);
- setFlag(EntityFlag.CHARGED, hasCrossbow);
+ ItemData activeCrossbow = null;
+ if (this.hand.getDefinition() == crossbow.getBedrockDefinition()) {
+ activeCrossbow = this.hand;
+ } else if (this.offhand.getDefinition() == crossbow.getBedrockDefinition()) {
+ activeCrossbow = this.offhand;
+ }
+
+ if (activeCrossbow != null) {
+ if (activeCrossbow.getTag() != null && activeCrossbow.getTag().containsKey("chargedItem")) {
+ dirtyMetadata.put(EntityDataTypes.CHARGE_AMOUNT, Byte.MAX_VALUE);
+ setFlag(EntityFlag.CHARGING, false);
+ setFlag(EntityFlag.CHARGED, true);
+ setFlag(EntityFlag.USING_ITEM, true);
+ } else if (getFlag(EntityFlag.CHARGED)) {
+ dirtyMetadata.put(EntityDataTypes.CHARGE_AMOUNT, (byte) 0);
+ setFlag(EntityFlag.CHARGED, false);
+ setFlag(EntityFlag.USING_ITEM, false);
+ }
+ }
updateBedrockMetadata();
}
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/raid/RavagerEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/raid/RavagerEntity.java
new file mode 100644
index 000000000..6190bae10
--- /dev/null
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/raid/RavagerEntity.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2019-2024 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.type.living.monster.raid;
+
+import org.cloudburstmc.math.vector.Vector3f;
+import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
+import org.geysermc.geyser.entity.EntityDefinition;
+import org.geysermc.geyser.session.GeyserSession;
+
+import java.util.UUID;
+import java.util.concurrent.TimeUnit;
+
+public class RavagerEntity extends RaidParticipantEntity {
+
+ public RavagerEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
+ super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
+ }
+
+ @Override
+ public boolean useArmSwingAttack() {
+ setFlag(EntityFlag.DELAYED_ATTACK, false);
+ updateBedrockMetadata();
+
+ session.scheduleInEventLoop(() -> {
+ setFlag(EntityFlag.DELAYED_ATTACK, true);
+ updateBedrockMetadata();
+ }, 75, TimeUnit.MILLISECONDS);
+
+ return true;
+ }
+}
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/raid/VindicatorEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/raid/VindicatorEntity.java
index 04a58addd..a2557e75a 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/raid/VindicatorEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/raid/VindicatorEntity.java
@@ -26,6 +26,7 @@
package org.geysermc.geyser.entity.type.living.monster.raid;
import org.cloudburstmc.math.vector.Vector3f;
+import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.session.GeyserSession;
@@ -37,6 +38,7 @@ public class VindicatorEntity extends AbstractIllagerEntity {
public VindicatorEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
+ dirtyMetadata.put(EntityDataTypes.TARGET_EID, session.getPlayerEntity().getGeyserId());
}
@Override
@@ -46,4 +48,9 @@ public class VindicatorEntity extends AbstractIllagerEntity {
byte xd = entityMetadata.getPrimitiveValue();
setFlag(EntityFlag.ANGRY, (xd & 4) == 4);
}
+
+ @Override
+ public boolean useArmSwingAttack() {
+ return true;
+ }
}
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/player/PlayerEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/player/PlayerEntity.java
index 25040063e..4c67b882f 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/player/PlayerEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/player/PlayerEntity.java
@@ -41,6 +41,7 @@ import org.cloudburstmc.protocol.bedrock.data.command.CommandPermission;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityLinkData;
+import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
import org.cloudburstmc.protocol.bedrock.packet.*;
import org.geysermc.geyser.api.entity.type.player.GeyserPlayerEntity;
import org.geysermc.geyser.entity.EntityDefinitions;
@@ -166,6 +167,31 @@ public class PlayerEntity extends LivingEntity implements GeyserPlayerEntity {
session.sendUpstreamPacket(addPlayerPacket);
}
+ @Override
+ public void despawnEntity() {
+ super.despawnEntity();
+
+ // Since we re-use player entities: Clear flags, held item, etc
+ this.resetMetadata();
+ this.hand = ItemData.AIR;
+ this.offhand = ItemData.AIR;
+ this.boots = ItemData.AIR;
+ this.leggings = ItemData.AIR;
+ this.chestplate = ItemData.AIR;
+ this.helmet = ItemData.AIR;
+ }
+
+ public void resetMetadata() {
+ // Reset all metadata to their default values
+ // This is used when a player respawns
+ this.flags.clear();
+ this.initializeMetadata();
+
+ // Explicitly reset all metadata not handled by initializeMetadata
+ setParrot(null, true);
+ setParrot(null, false);
+ }
+
public void sendPlayer() {
if (session.getEntityCache().getPlayerEntity(uuid) == null)
return;
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/player/SessionPlayerEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/player/SessionPlayerEntity.java
index e10adb134..45fea4d48 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/player/SessionPlayerEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/player/SessionPlayerEntity.java
@@ -27,14 +27,18 @@ package org.geysermc.geyser.entity.type.player;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import lombok.Getter;
+import lombok.Setter;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.protocol.bedrock.data.AttributeData;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
+import org.cloudburstmc.protocol.bedrock.packet.MovePlayerPacket;
import org.cloudburstmc.protocol.bedrock.packet.UpdateAttributesPacket;
import org.geysermc.geyser.entity.attribute.GeyserAttributeType;
import org.geysermc.geyser.item.Items;
+import org.geysermc.geyser.network.GameProtocol;
+import org.geysermc.geyser.level.BedrockDimension;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.util.AttributeUtils;
import org.geysermc.geyser.util.DimensionUtils;
@@ -60,16 +64,23 @@ public class SessionPlayerEntity extends PlayerEntity {
*/
@Getter
protected final Map attributes = new Object2ObjectOpenHashMap<>();
- /**
- * Whether to check for updated speed after all entity metadata has been processed
- */
- private boolean refreshSpeed = false;
/**
* Used in PlayerInputTranslator for movement checks.
*/
@Getter
private boolean isRidingInFront;
+ private int lastAirSupply = getMaxAir();
+
+ /**
+ * Determines if our position is currently out-of-sync with the Java server
+ * due to our workaround for the void floor
+ *
+ * Must be reset when dying, switching worlds, or being teleported out of the void
+ */
+ @Getter @Setter
+ private boolean voidPositionDesynched;
+
public SessionPlayerEntity(GeyserSession session) {
super(session, -1, 1, null, Vector3f.ZERO, Vector3f.ZERO, 0, 0, 0, null, null);
@@ -88,10 +99,25 @@ public class SessionPlayerEntity extends PlayerEntity {
@Override
public void moveRelative(double relX, double relY, double relZ, float yaw, float pitch, float headYaw, boolean isOnGround) {
+ if (voidPositionDesynched) {
+ if (!isBelowVoidFloor()) {
+ voidPositionDesynched = false; // No need to fix our offset; we've been moved
+ }
+ }
super.moveRelative(relX, relY, relZ, yaw, pitch, headYaw, isOnGround);
session.getCollisionManager().updatePlayerBoundingBox(this.position.down(definition.offset()));
}
+ @Override
+ public void moveAbsolute(Vector3f position, float yaw, float pitch, float headYaw, boolean isOnGround, boolean teleported) {
+ if (voidPositionDesynched) {
+ if (!isBelowVoidFloor()) {
+ voidPositionDesynched = false; // No need to fix our offset; we've been moved
+ }
+ }
+ super.moveAbsolute(position, yaw, pitch, headYaw, isOnGround, teleported);
+ }
+
@Override
public void setPosition(Vector3f position) {
if (valid) { // Don't update during session init
@@ -120,9 +146,7 @@ public class SessionPlayerEntity extends PlayerEntity {
// TODO: proper fix, BDS somehow does it? https://paste.gg/p/anonymous/3adfb7612f1540be80fa03a2281f93dc (BDS 1.20.13)
if (!this.session.getGameMode().equals(GameMode.SPECTATOR)) {
super.setFlags(entityMetadata);
- session.setSwimmingInWater((entityMetadata.getPrimitiveValue() & 0x10) == 0x10 && getFlag(EntityFlag.SPRINTING));
}
- refreshSpeed = true;
}
/**
@@ -150,7 +174,6 @@ public class SessionPlayerEntity extends PlayerEntity {
public void setPose(Pose pose) {
super.setPose(pose);
session.setPose(pose);
- refreshSpeed = true;
}
public float getMaxHealth() {
@@ -167,7 +190,13 @@ public class SessionPlayerEntity extends PlayerEntity {
@Override
protected void setAirSupply(int amount) {
- if (amount == getMaxAir()) {
+ // Seemingly required to be sent as of Bedrock 1.21. Otherwise, bubbles will appear as empty
+ // Also, this changes how the air bubble graphics/sounds are presented. Breathing on means sound effects and
+ // the bubbles visually pop
+ setFlag(EntityFlag.BREATHING, amount >= this.lastAirSupply);
+ this.lastAirSupply = amount;
+
+ if (amount == getMaxAir() && GameProtocol.isPre1_21_0(session)) {
super.setAirSupply(0); // Hide the bubble counter from the UI for the player
} else {
super.setAirSupply(amount);
@@ -199,21 +228,6 @@ public class SessionPlayerEntity extends PlayerEntity {
}
}
- @Override
- public void updateBedrockMetadata() {
- super.updateBedrockMetadata();
- if (refreshSpeed) {
- AttributeData speedAttribute = session.adjustSpeed();
- if (speedAttribute != null) {
- UpdateAttributesPacket attributesPacket = new UpdateAttributesPacket();
- attributesPacket.setRuntimeEntityId(geyserId);
- attributesPacket.setAttributes(Collections.singletonList(speedAttribute));
- session.sendUpstreamPacket(attributesPacket);
- }
- refreshSpeed = false;
- }
- }
-
@Override
protected void updateAttribute(Attribute javaAttribute, List newAttributes) {
if (javaAttribute.getType() == AttributeType.Builtin.GENERIC_ATTACK_SPEED) {
@@ -226,17 +240,6 @@ public class SessionPlayerEntity extends PlayerEntity {
@Override
protected AttributeData calculateAttribute(Attribute javaAttribute, GeyserAttributeType type) {
AttributeData attributeData = super.calculateAttribute(javaAttribute, type);
-
- if (javaAttribute.getType() == AttributeType.Builtin.GENERIC_MOVEMENT_SPEED) {
- session.setOriginalSpeedAttribute(attributeData.getValue());
- AttributeData speedAttribute = session.adjustSpeed();
- if (speedAttribute != null) {
- // Overwrite the attribute with our own
- this.attributes.put(type, speedAttribute);
- return speedAttribute;
- }
- }
-
this.attributes.put(type, attributeData);
return attributeData;
}
@@ -244,11 +247,14 @@ public class SessionPlayerEntity extends PlayerEntity {
public void setLastDeathPosition(@Nullable GlobalPos pos) {
if (pos != null) {
dirtyMetadata.put(EntityDataTypes.PLAYER_LAST_DEATH_POS, pos.getPosition());
- dirtyMetadata.put(EntityDataTypes.PLAYER_LAST_DEATH_DIMENSION, DimensionUtils.javaToBedrock(pos.getDimension()));
+ dirtyMetadata.put(EntityDataTypes.PLAYER_LAST_DEATH_DIMENSION, DimensionUtils.javaToBedrock(pos.getDimension().asString()));
dirtyMetadata.put(EntityDataTypes.PLAYER_HAS_DIED, true);
} else {
dirtyMetadata.put(EntityDataTypes.PLAYER_HAS_DIED, false);
}
+
+ // We're either respawning or switching worlds, either way, we are no longer desynched
+ this.setVoidPositionDesynched(false);
}
@Override
@@ -264,19 +270,13 @@ public class SessionPlayerEntity extends PlayerEntity {
super.setAbsorptionHearts(entityMetadata);
}
+ @Override
public void resetMetadata() {
- // Reset all metadata to their default values
- // This is used when a player respawns
- this.flags.clear();
- this.initializeMetadata();
+ super.resetMetadata();
// Reset air
this.resetAir();
- // Explicitly reset all metadata not handled by initializeMetadata
- setParrot(null, true);
- setParrot(null, false);
-
// Absorption is metadata in java edition
attributes.remove(GeyserAttributeType.ABSORPTION);
UpdateAttributesPacket attributesPacket = new UpdateAttributesPacket();
@@ -306,4 +306,48 @@ public class SessionPlayerEntity extends PlayerEntity {
public void resetAir() {
this.setAirSupply(getMaxAir());
}
+
+ private boolean isBelowVoidFloor() {
+ return position.getY() < voidFloorPosition();
+ }
+
+ public int voidFloorPosition() {
+ // The void floor is offset about 40 blocks below the bottom of the world
+ BedrockDimension bedrockDimension = session.getChunkCache().getBedrockDimension();
+ return bedrockDimension.minY() - 40;
+ }
+
+ /**
+ * This method handles teleporting the player below or above the Bedrock void floor.
+ * The Java server should never see this desync as we adjust the position that we send to it
+ *
+ * @param up in which direction to teleport - true to resync our position, or false to be
+ * teleported below the void floor.
+ */
+ public void teleportVoidFloorFix(boolean up) {
+ // Safety to avoid double teleports
+ if ((voidPositionDesynched && !up) || (!voidPositionDesynched && up)) {
+ return;
+ }
+
+ // Work around there being a floor at the bottom of the world and teleport the player below it
+ // Moving from below to above the void floor works fine
+ Vector3f newPosition = this.getPosition();
+ if (up) {
+ newPosition = newPosition.up(4f);
+ voidPositionDesynched = false;
+ } else {
+ newPosition = newPosition.down(4f);
+ voidPositionDesynched = true;
+ }
+
+ this.setPositionManual(newPosition);
+ MovePlayerPacket movePlayerPacket = new MovePlayerPacket();
+ movePlayerPacket.setRuntimeEntityId(geyserId);
+ movePlayerPacket.setPosition(newPosition);
+ movePlayerPacket.setRotation(getBedrockRotation());
+ movePlayerPacket.setMode(MovePlayerPacket.Mode.TELEPORT);
+ movePlayerPacket.setTeleportationCause(MovePlayerPacket.TeleportationCause.BEHAVIOR);
+ session.sendUpstreamPacketImmediately(movePlayerPacket);
+ }
}
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/player/SkullPlayerEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/player/SkullPlayerEntity.java
index 89f9c37d6..1c5060de0 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/player/SkullPlayerEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/player/SkullPlayerEntity.java
@@ -34,7 +34,10 @@ import org.cloudburstmc.protocol.bedrock.data.command.CommandPermission;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.cloudburstmc.protocol.bedrock.packet.AddPlayerPacket;
-import org.geysermc.geyser.level.block.BlockStateValues;
+import org.geysermc.geyser.level.block.property.Properties;
+import org.geysermc.geyser.level.block.type.BlockState;
+import org.geysermc.geyser.level.block.type.WallSkullBlock;
+import org.geysermc.geyser.level.physics.Direction;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.session.cache.SkullCache;
import org.geysermc.geyser.skin.SkullSkinManager;
@@ -137,20 +140,19 @@ public class SkullPlayerEntity extends PlayerEntity {
float z = skull.getPosition().getZ() + .5f;
float rotation;
- int blockState = skull.getBlockState();
- byte floorRotation = BlockStateValues.getSkullRotation(blockState);
- if (floorRotation == -1) {
- // Wall skull
+ BlockState blockState = skull.getBlockState();
+ if (blockState.block() instanceof WallSkullBlock) {
y += 0.25f;
- rotation = BlockStateValues.getSkullWallDirections().get(blockState);
- switch ((int) rotation) {
- case 180 -> z += 0.24f; // North
- case 0 -> z -= 0.24f; // South
- case 90 -> x += 0.24f; // West
- case 270 -> x -= 0.24f; // East
+ Direction direction = blockState.getValue(Properties.HORIZONTAL_FACING);
+ rotation = WallSkullBlock.getDegrees(direction);
+ switch (direction) {
+ case NORTH -> z += 0.24f;
+ case SOUTH -> z -= 0.24f;
+ case WEST -> x += 0.24f;
+ case EAST -> x -= 0.24f;
}
} else {
- rotation = (180f + (floorRotation * 22.5f)) % 360;
+ rotation = (180f + blockState.getValue(Properties.ROTATION_16, 0) * 22.5f) % 360;
}
moveAbsolute(Vector3f.from(x, y, z), rotation, 0, rotation, true, true);
diff --git a/core/src/main/java/org/geysermc/geyser/erosion/GeyserboundPacketHandlerImpl.java b/core/src/main/java/org/geysermc/geyser/erosion/GeyserboundPacketHandlerImpl.java
index a62f9ec49..c8cbe384b 100644
--- a/core/src/main/java/org/geysermc/geyser/erosion/GeyserboundPacketHandlerImpl.java
+++ b/core/src/main/java/org/geysermc/geyser/erosion/GeyserboundPacketHandlerImpl.java
@@ -25,14 +25,13 @@
package org.geysermc.geyser.erosion;
-import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents;
-import org.geysermc.mcprotocollib.protocol.data.game.level.block.value.PistonValueType;
import io.netty.channel.Channel;
+import it.unimi.dsi.fastutil.Pair;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectMaps;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
-import it.unimi.dsi.fastutil.objects.Object2IntArrayMap;
-import it.unimi.dsi.fastutil.objects.Object2IntMap;
+import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap;
+import it.unimi.dsi.fastutil.objects.Object2ObjectMap;
import lombok.Getter;
import lombok.Setter;
import org.cloudburstmc.math.vector.Vector3i;
@@ -43,21 +42,18 @@ import org.geysermc.erosion.packet.ErosionPacketHandler;
import org.geysermc.erosion.packet.ErosionPacketSender;
import org.geysermc.erosion.packet.backendbound.BackendboundInitializePacket;
import org.geysermc.erosion.packet.backendbound.BackendboundPacket;
-import org.geysermc.erosion.packet.geyserbound.GeyserboundBatchBlockIdPacket;
-import org.geysermc.erosion.packet.geyserbound.GeyserboundBlockEntityPacket;
-import org.geysermc.erosion.packet.geyserbound.GeyserboundBlockIdPacket;
-import org.geysermc.erosion.packet.geyserbound.GeyserboundBlockLookupFailPacket;
-import org.geysermc.erosion.packet.geyserbound.GeyserboundBlockPlacePacket;
-import org.geysermc.erosion.packet.geyserbound.GeyserboundHandshakePacket;
-import org.geysermc.erosion.packet.geyserbound.GeyserboundPickBlockPacket;
-import org.geysermc.erosion.packet.geyserbound.GeyserboundPistonEventPacket;
+import org.geysermc.erosion.packet.geyserbound.*;
import org.geysermc.geyser.level.block.BlockStateValues;
+import org.geysermc.geyser.level.block.property.Properties;
+import org.geysermc.geyser.level.block.type.Block;
+import org.geysermc.geyser.level.block.type.BlockState;
import org.geysermc.geyser.level.physics.Direction;
import org.geysermc.geyser.network.GameProtocol;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.session.cache.PistonCache;
import org.geysermc.geyser.translator.level.block.entity.PistonBlockEntity;
import org.geysermc.geyser.util.BlockEntityUtils;
+import org.geysermc.mcprotocollib.protocol.data.game.level.block.value.PistonValueType;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicInteger;
@@ -71,7 +67,7 @@ public final class GeyserboundPacketHandlerImpl extends AbstractGeyserboundPacke
@Setter
private CompletableFuture pendingBatchLookup = null;
@Setter
- private CompletableFuture pickBlockLookup = null;
+ private CompletableFuture> pickBlockLookup = null;
private final AtomicInteger nextTransactionId = new AtomicInteger(1);
@@ -127,7 +123,7 @@ public final class GeyserboundPacketHandlerImpl extends AbstractGeyserboundPacke
}
CompletableFuture future = this.asyncPendingLookups.remove(transactionId);
if (future != null) {
- future.complete(BlockStateValues.JAVA_AIR_ID);
+ future.complete(Block.JAVA_AIR_ID);
}
}
@@ -141,28 +137,29 @@ public final class GeyserboundPacketHandlerImpl extends AbstractGeyserboundPacke
placeBlockSoundPacket.setIdentifier(":");
session.sendUpstreamPacket(placeBlockSoundPacket);
session.setLastBlockPlacePosition(null);
- session.setLastBlockPlacedId(null);
+ session.setLastBlockPlaced(null);
}
@Override
public void handlePickBlock(GeyserboundPickBlockPacket packet) {
if (this.pickBlockLookup != null) {
- //this.pickBlockLookup.complete(packet.getTag()); // TODO 1.20.5
+ this.pickBlockLookup.complete(packet.getComponents());
}
}
@Override
public void handlePistonEvent(GeyserboundPistonEventPacket packet) {
- Direction orientation = BlockStateValues.getPistonOrientation(packet.getBlockId());
+ Direction orientation = BlockState.of(packet.getBlockId()).getValue(Properties.FACING);
Vector3i position = packet.getPos();
boolean isExtend = packet.isExtend();
var stream = packet.getAttachedBlocks()
.object2IntEntrySet()
.stream()
- .filter(entry -> BlockStateValues.canPistonMoveBlock(entry.getIntValue(), isExtend));
- Object2IntMap attachedBlocks = new Object2IntArrayMap<>();
- stream.forEach(entry -> attachedBlocks.put(entry.getKey(), entry.getIntValue()));
+ .map(entry -> Pair.of(entry.getKey(), BlockState.of(entry.getIntValue())))
+ .filter(pair -> BlockStateValues.canPistonMoveBlock(pair.value(), isExtend));
+ Object2ObjectMap attachedBlocks = new Object2ObjectArrayMap<>();
+ stream.forEach(pair -> attachedBlocks.put(pair.key(), pair.value()));
session.executeInEventLoop(() -> {
PistonCache pistonCache = session.getPistonCache();
diff --git a/core/src/main/java/org/geysermc/geyser/impl/camera/GeyserCameraData.java b/core/src/main/java/org/geysermc/geyser/impl/camera/GeyserCameraData.java
index 2a93c89e3..7582502b3 100644
--- a/core/src/main/java/org/geysermc/geyser/impl/camera/GeyserCameraData.java
+++ b/core/src/main/java/org/geysermc/geyser/impl/camera/GeyserCameraData.java
@@ -32,24 +32,50 @@ import org.cloudburstmc.math.vector.Vector2f;
import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.protocol.bedrock.data.CameraShakeAction;
import org.cloudburstmc.protocol.bedrock.data.CameraShakeType;
+import org.cloudburstmc.protocol.bedrock.data.HudElement;
+import org.cloudburstmc.protocol.bedrock.data.HudVisibility;
import org.cloudburstmc.protocol.bedrock.data.camera.CameraEase;
import org.cloudburstmc.protocol.bedrock.data.camera.CameraFadeInstruction;
import org.cloudburstmc.protocol.bedrock.data.camera.CameraSetInstruction;
import org.cloudburstmc.protocol.bedrock.packet.CameraInstructionPacket;
import org.cloudburstmc.protocol.bedrock.packet.CameraShakePacket;
import org.cloudburstmc.protocol.bedrock.packet.PlayerFogPacket;
-import org.geysermc.geyser.api.bedrock.camera.*;
+import org.cloudburstmc.protocol.bedrock.packet.SetHudPacket;
+import org.geysermc.geyser.api.bedrock.camera.CameraData;
+import org.geysermc.geyser.api.bedrock.camera.CameraEaseType;
+import org.geysermc.geyser.api.bedrock.camera.CameraFade;
+import org.geysermc.geyser.api.bedrock.camera.CameraPerspective;
+import org.geysermc.geyser.api.bedrock.camera.CameraPosition;
+import org.geysermc.geyser.api.bedrock.camera.CameraShake;
+import org.geysermc.geyser.api.bedrock.camera.GuiElement;
import org.geysermc.geyser.session.GeyserSession;
+import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode;
-import java.util.*;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Objects;
+import java.util.Set;
+import java.util.UUID;
public class GeyserCameraData implements CameraData {
+ private static final HudElement[] HUD_ELEMENT_VALUES = HudElement.values();
+ private static final Set ALL_HUD_ELEMENTS = Set.of(HUD_ELEMENT_VALUES);
+
+ /**
+ * An array of elements to hide when the player is in spectator mode.
+ * Helps with tidying up the GUI; Java-style.
+ */
+ private static final GuiElement[] SPECTATOR_HIDDEN_ELEMENTS = {
+ GuiElement.AIR_BUBBLES_BAR,
+ GuiElement.ARMOR,
+ GuiElement.HEALTH,
+ GuiElement.FOOD_BAR,
+ GuiElement.PROGRESS_BAR,
+ GuiElement.TOOL_TIPS
+ };
private final GeyserSession session;
- @Getter
- private CameraPerspective cameraPerspective;
-
/**
* All fog effects that are currently applied to the client.
*/
@@ -57,6 +83,14 @@ public class GeyserCameraData implements CameraData {
private final Set cameraLockOwners = new HashSet<>();
+ /**
+ * All currently hidden HUD elements
+ */
+ private final Set hiddenHudElements = new HashSet<>();
+
+ @Getter
+ private CameraPerspective cameraPerspective;
+
public GeyserCameraData(GeyserSession session) {
this.session = session;
}
@@ -223,4 +257,67 @@ public class GeyserCameraData implements CameraData {
public boolean isCameraLocked() {
return !this.cameraLockOwners.isEmpty();
}
-}
\ No newline at end of file
+
+ @Override
+ public void hideElement(GuiElement... elements) {
+ Objects.requireNonNull(elements);
+ SetHudPacket packet = new SetHudPacket();
+ packet.setVisibility(HudVisibility.HIDE);
+ Set elementSet = packet.getElements();
+
+ for (GuiElement element : elements) {
+ this.hiddenHudElements.add(element);
+ elementSet.add(HUD_ELEMENT_VALUES[element.id()]);
+ }
+
+ session.sendUpstreamPacket(packet);
+ }
+
+ @Override
+ public void resetElement(GuiElement... elements) {
+ SetHudPacket packet = new SetHudPacket();
+ packet.setVisibility(HudVisibility.RESET);
+ Set elementSet = packet.getElements();
+
+ if (elements != null && elements.length != 0) {
+ for (GuiElement element : elements) {
+ this.hiddenHudElements.remove(element);
+ elementSet.add(HUD_ELEMENT_VALUES[element.id()]);
+ }
+ } else {
+ this.hiddenHudElements.clear();
+ elementSet.addAll(ALL_HUD_ELEMENTS);
+ }
+
+ session.sendUpstreamPacket(packet);
+ }
+
+ @Override
+ public boolean isHudElementHidden(@NonNull GuiElement element) {
+ Objects.requireNonNull(element);
+ return this.hiddenHudElements.contains(element);
+ }
+
+ @Override
+ public @NonNull Set hiddenElements() {
+ return Collections.unmodifiableSet(hiddenHudElements);
+ }
+
+ /**
+ * Deals with hiding hud elements while in spectator.
+ *
+ * @param currentlySpectator whether the player is currently in spectator mode
+ * @param newGameMode the new GameMode to switch to
+ */
+ public void handleGameModeChange(boolean currentlySpectator, GameMode newGameMode) {
+ if (newGameMode == GameMode.SPECTATOR) {
+ if (!currentlySpectator) {
+ hideElement(SPECTATOR_HIDDEN_ELEMENTS);
+ }
+ } else {
+ if (currentlySpectator) {
+ resetElement(SPECTATOR_HIDDEN_ELEMENTS);
+ }
+ }
+ }
+}
diff --git a/core/src/main/java/org/geysermc/geyser/inventory/Container.java b/core/src/main/java/org/geysermc/geyser/inventory/Container.java
index 209aeb24f..e78a4d2c6 100644
--- a/core/src/main/java/org/geysermc/geyser/inventory/Container.java
+++ b/core/src/main/java/org/geysermc/geyser/inventory/Container.java
@@ -25,6 +25,7 @@
package org.geysermc.geyser.inventory;
+import org.geysermc.geyser.level.block.type.Block;
import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType;
import lombok.Getter;
import org.checkerframework.checker.nullness.qual.NonNull;
@@ -37,7 +38,7 @@ import org.jetbrains.annotations.Range;
*/
@Getter
public class Container extends Inventory {
- private final PlayerInventory playerInventory;
+ protected final PlayerInventory playerInventory;
private final int containerSize;
/**
@@ -83,9 +84,9 @@ public class Container extends Inventory {
* Will be overwritten for droppers.
*
* @param usingRealBlock whether this container is using a real container or not
- * @param javaBlockId the Java block string of the block, if real
+ * @param block the Java block, if real
*/
- public void setUsingRealBlock(boolean usingRealBlock, String javaBlockId) {
+ public void setUsingRealBlock(boolean usingRealBlock, Block block) {
isUsingRealBlock = usingRealBlock;
}
}
diff --git a/core/src/main/java/org/geysermc/geyser/inventory/CrafterContainer.java b/core/src/main/java/org/geysermc/geyser/inventory/CrafterContainer.java
index 41452bed6..fb118252d 100644
--- a/core/src/main/java/org/geysermc/geyser/inventory/CrafterContainer.java
+++ b/core/src/main/java/org/geysermc/geyser/inventory/CrafterContainer.java
@@ -25,13 +25,19 @@
package org.geysermc.geyser.inventory;
+import org.checkerframework.checker.nullness.qual.NonNull;
+import org.geysermc.geyser.session.GeyserSession;
+import org.geysermc.geyser.translator.inventory.CrafterInventoryTranslator;
+import org.geysermc.geyser.translator.inventory.InventoryTranslator;
import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType;
import lombok.Getter;
import lombok.Setter;
import org.geysermc.geyser.GeyserImpl;
+import org.jetbrains.annotations.Range;
@Getter
public class CrafterContainer extends Container {
+ private GeyserItemStack resultItem = GeyserItemStack.EMPTY;
@Setter
private boolean triggered = false;
@@ -46,8 +52,36 @@ public class CrafterContainer extends Container {
super(title, id, size, containerType, playerInventory);
}
+ @Override
+ public GeyserItemStack getItem(int slot) {
+ if (slot == CrafterInventoryTranslator.JAVA_RESULT_SLOT) {
+ return this.resultItem;
+ } else if (isCraftingGrid(slot)) {
+ return super.getItem(slot);
+ } else {
+ return playerInventory.getItem(slot - CrafterInventoryTranslator.GRID_SIZE + InventoryTranslator.PLAYER_INVENTORY_OFFSET);
+ }
+ }
+
+ @Override
+ public int getOffsetForHotbar(@Range(from = 0, to = 8) int slot) {
+ return playerInventory.getOffsetForHotbar(slot) - InventoryTranslator.PLAYER_INVENTORY_OFFSET + CrafterInventoryTranslator.GRID_SIZE;
+ }
+
+ @Override
+ public void setItem(int slot, @NonNull GeyserItemStack newItem, GeyserSession session) {
+ if (slot == CrafterInventoryTranslator.JAVA_RESULT_SLOT) {
+ // Result item probably won't be an item that needs to worry about net ID or lodestone compasses
+ this.resultItem = newItem;
+ } else if (isCraftingGrid(slot)) {
+ super.setItem(slot, newItem, session);
+ } else {
+ playerInventory.setItem(slot - CrafterInventoryTranslator.GRID_SIZE + InventoryTranslator.PLAYER_INVENTORY_OFFSET, newItem, session);
+ }
+ }
+
public void setSlot(int slot, boolean enabled) {
- if (slot < 0 || slot > 8) {
+ if (!isCraftingGrid(slot)) {
GeyserImpl.getInstance().getLogger().warning("Crafter slot out of bounds: " + slot);
return;
}
@@ -58,4 +92,8 @@ public class CrafterContainer extends Container {
disabledSlotsMask = (short) (disabledSlotsMask | (1 << slot));
}
}
+
+ private static boolean isCraftingGrid(int slot) {
+ return slot >= 0 && slot <= 8;
+ }
}
diff --git a/core/src/main/java/org/geysermc/geyser/inventory/Generic3X3Container.java b/core/src/main/java/org/geysermc/geyser/inventory/Generic3X3Container.java
index 65e47d877..0b14d1105 100644
--- a/core/src/main/java/org/geysermc/geyser/inventory/Generic3X3Container.java
+++ b/core/src/main/java/org/geysermc/geyser/inventory/Generic3X3Container.java
@@ -26,6 +26,8 @@
package org.geysermc.geyser.inventory;
import lombok.Getter;
+import org.geysermc.geyser.level.block.Blocks;
+import org.geysermc.geyser.level.block.type.Block;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.inventory.Generic3X3InventoryTranslator;
import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType;
@@ -44,10 +46,10 @@ public class Generic3X3Container extends Container {
}
@Override
- public void setUsingRealBlock(boolean usingRealBlock, String javaBlockId) {
- super.setUsingRealBlock(usingRealBlock, javaBlockId);
+ public void setUsingRealBlock(boolean usingRealBlock, Block block) {
+ super.setUsingRealBlock(usingRealBlock, block);
if (usingRealBlock) {
- isDropper = javaBlockId.startsWith("minecraft:dropper");
+ isDropper = block == Blocks.DROPPER;
}
}
}
diff --git a/core/src/main/java/org/geysermc/geyser/inventory/GeyserEnchantOption.java b/core/src/main/java/org/geysermc/geyser/inventory/GeyserEnchantOption.java
index 23365e392..de0bd7300 100644
--- a/core/src/main/java/org/geysermc/geyser/inventory/GeyserEnchantOption.java
+++ b/core/src/main/java/org/geysermc/geyser/inventory/GeyserEnchantOption.java
@@ -25,12 +25,11 @@
package org.geysermc.geyser.inventory;
+import lombok.Getter;
import org.cloudburstmc.protocol.bedrock.data.inventory.EnchantData;
import org.cloudburstmc.protocol.bedrock.data.inventory.EnchantOptionData;
-import lombok.Getter;
import org.geysermc.geyser.session.GeyserSession;
-import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@@ -44,13 +43,13 @@ public class GeyserEnchantOption {
* is controlled by the server.
* So, of course, we have to throw in some easter eggs. ;)
*/
- private static final List ENCHANT_NAMES = Arrays.asList("tougher armor", "lukeeey", "fall better",
- "explode less", "camo toy", "breathe better", "rtm five one six", "armor stab", "water walk", "you are elsa",
- "tim two zero three", "fast walk nether", "davchoo", "oof ouch owie", "enemy on fire", "spider sad", "aj ferguson", "redned",
- "more items thx", "long sword reach", "fast tool", "give me block", "less breaky break", "cube craft",
- "strong arrow", "fist arrow", "spicy arrow", "many many arrows", "geyser", "come here fish", "i like this",
- "stabby stab", "supreme mortal", "avatar i guess", "more arrows", "fly finder seventeen", "in and out",
- "xp heals tools", "dragon proxy waz here");
+ private static final List ENCHANT_NAMES = List.of("tougher armor", "lukeeey", "fall better",
+ "explode less", "camo toy", "armor stab", "breathe better", "water walk", "rtm five one six", "oof ouch owie",
+ "enemy on fire", "spider sad", "aj ferguson", "redned", "more items thx", "fast tool", "give me block",
+ "less breaky break", "cube craft", "strong arrow", "fist arrow", "spicy arrow", "many many arrows", "geyser",
+ "come here fish", "you are elsa", "xp heals tools", "tim two zero three", "dragon proxy waz here",
+ "stabby stab", "supreme mortal", "i like this", "avatar i guess", "more arrows", "in and out",
+ "fly finder seventeen", "fast walk nether", "davchoo", "onechris", "death bringer thirteen", "kastle");
@Getter
private final int javaIndex;
@@ -62,7 +61,6 @@ public class GeyserEnchantOption {
private boolean hasChanged;
private int xpCost = 0;
- private int javaEnchantIndex = -1;
private int bedrockEnchantIndex = -1;
private int enchantLevel = -1;
@@ -74,7 +72,7 @@ public class GeyserEnchantOption {
this.hasChanged = false;
return new EnchantOptionData(xpCost, javaIndex + 16, EMPTY,
enchantLevel == -1 ? EMPTY : Collections.singletonList(new EnchantData(bedrockEnchantIndex, enchantLevel)), EMPTY,
- javaEnchantIndex == -1 ? "unknown" : ENCHANT_NAMES.get(javaEnchantIndex), enchantLevel == -1 ? 0 : session.getNextItemNetId());
+ bedrockEnchantIndex == -1 ? "unknown" : ENCHANT_NAMES.get(bedrockEnchantIndex), enchantLevel == -1 ? 0 : session.getNextItemNetId());
}
public boolean hasChanged() {
@@ -88,10 +86,9 @@ public class GeyserEnchantOption {
}
}
- public void setEnchantIndex(int javaEnchantIndex, int bedrockEnchantIndex) {
- if (this.javaEnchantIndex != javaEnchantIndex) {
+ public void setEnchantIndex(int bedrockEnchantIndex) {
+ if (this.bedrockEnchantIndex != bedrockEnchantIndex) {
hasChanged = true;
- this.javaEnchantIndex = javaEnchantIndex;
this.bedrockEnchantIndex = bedrockEnchantIndex;
}
}
diff --git a/core/src/main/java/org/geysermc/geyser/inventory/GeyserItemStack.java b/core/src/main/java/org/geysermc/geyser/inventory/GeyserItemStack.java
index fa62769fe..744ad70b6 100644
--- a/core/src/main/java/org/geysermc/geyser/inventory/GeyserItemStack.java
+++ b/core/src/main/java/org/geysermc/geyser/inventory/GeyserItemStack.java
@@ -69,7 +69,7 @@ public class GeyserItemStack {
return of(javaId, amount, null);
}
- public static @NonNull GeyserItemStack of(int javaId, int amount, DataComponents components) {
+ public static @NonNull GeyserItemStack of(int javaId, int amount, @Nullable DataComponents components) {
return new GeyserItemStack(javaId, amount, components);
}
diff --git a/core/src/main/java/org/geysermc/geyser/inventory/holder/BlockInventoryHolder.java b/core/src/main/java/org/geysermc/geyser/inventory/holder/BlockInventoryHolder.java
index c11505ffb..cdda4fe4c 100644
--- a/core/src/main/java/org/geysermc/geyser/inventory/holder/BlockInventoryHolder.java
+++ b/core/src/main/java/org/geysermc/geyser/inventory/holder/BlockInventoryHolder.java
@@ -36,11 +36,11 @@ import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.inventory.Container;
import org.geysermc.geyser.inventory.Inventory;
import org.geysermc.geyser.inventory.LecternContainer;
+import org.geysermc.geyser.level.block.type.Block;
+import org.geysermc.geyser.level.block.type.BlockState;
import org.geysermc.geyser.registry.BlockRegistries;
-import org.geysermc.geyser.registry.type.BlockMapping;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.inventory.InventoryTranslator;
-import org.geysermc.geyser.util.BlockUtils;
import org.geysermc.geyser.util.InventoryUtils;
import java.util.Collections;
@@ -55,20 +55,24 @@ public class BlockInventoryHolder extends InventoryHolder {
/**
* The default Java block ID to translate as a fake block
*/
- private final int defaultJavaBlockState;
+ private final BlockState defaultJavaBlockState;
private final ContainerType containerType;
- private final Set validBlocks;
+ private final Set validBlocks;
- public BlockInventoryHolder(String javaBlockIdentifier, ContainerType containerType, String... validBlocks) {
- this.defaultJavaBlockState = BlockRegistries.JAVA_IDENTIFIER_TO_ID.get().getInt(javaBlockIdentifier);
+ public BlockInventoryHolder(Block defaultJavaBlock, ContainerType containerType, Block... validBlocks) {
+ this(defaultJavaBlock.defaultBlockState(), containerType, validBlocks);
+ }
+
+ public BlockInventoryHolder(BlockState defaultJavaBlockState, ContainerType containerType, Block... validBlocks) {
+ this.defaultJavaBlockState = defaultJavaBlockState;
this.containerType = containerType;
if (validBlocks != null) {
- Set validBlocksTemp = new HashSet<>(validBlocks.length + 1);
+ Set validBlocksTemp = new HashSet<>(validBlocks.length + 1);
Collections.addAll(validBlocksTemp, validBlocks);
- validBlocksTemp.add(BlockUtils.getCleanIdentifier(javaBlockIdentifier));
+ validBlocksTemp.add(defaultJavaBlockState.block());
this.validBlocks = Set.copyOf(validBlocksTemp);
} else {
- this.validBlocks = Collections.singleton(BlockUtils.getCleanIdentifier(javaBlockIdentifier));
+ this.validBlocks = Collections.singleton(defaultJavaBlockState.block());
}
}
@@ -80,14 +84,13 @@ public class BlockInventoryHolder extends InventoryHolder {
if (checkInteractionPosition(session)) {
// Then, check to see if the interacted block is valid for this inventory by ensuring the block state identifier is valid
// and the bedrock block is vanilla
- int javaBlockId = session.getGeyser().getWorldManager().getBlockAt(session, session.getLastInteractionBlockPosition());
- if (!BlockRegistries.CUSTOM_BLOCK_STATE_OVERRIDES.get().containsKey(javaBlockId)) {
- String[] javaBlockString = BlockRegistries.JAVA_BLOCKS.getOrDefault(javaBlockId, BlockMapping.DEFAULT).getJavaIdentifier().split("\\[");
- if (isValidBlock(javaBlockString)) {
+ BlockState state = session.getGeyser().getWorldManager().blockAt(session, session.getLastInteractionBlockPosition());
+ if (!BlockRegistries.CUSTOM_BLOCK_STATE_OVERRIDES.get().containsKey(state.javaId())) {
+ if (isValidBlock(state)) {
// We can safely use this block
inventory.setHolderPosition(session.getLastInteractionBlockPosition());
- ((Container) inventory).setUsingRealBlock(true, javaBlockString[0]);
- setCustomName(session, session.getLastInteractionBlockPosition(), inventory, javaBlockId);
+ ((Container) inventory).setUsingRealBlock(true, state.block());
+ setCustomName(session, session.getLastInteractionBlockPosition(), inventory, state);
return true;
}
@@ -125,11 +128,11 @@ public class BlockInventoryHolder extends InventoryHolder {
/**
* @return true if this Java block ID can be used for player inventory.
*/
- protected boolean isValidBlock(String[] javaBlockString) {
- return this.validBlocks.contains(javaBlockString[0]);
+ protected boolean isValidBlock(BlockState blockState) {
+ return this.validBlocks.contains(blockState.block());
}
- protected void setCustomName(GeyserSession session, Vector3i position, Inventory inventory, int javaBlockState) {
+ protected void setCustomName(GeyserSession session, Vector3i position, Inventory inventory, BlockState javaBlockState) {
NbtMap tag = NbtMap.builder()
.putInt("x", position.getX())
.putInt("y", position.getY())
@@ -160,6 +163,7 @@ public class BlockInventoryHolder extends InventoryHolder {
ContainerClosePacket packet = new ContainerClosePacket();
packet.setId((byte) inventory.getBedrockId());
packet.setServerInitiated(true);
+ packet.setType(ContainerType.CONTAINER);
session.sendUpstreamPacket(packet);
return;
}
diff --git a/core/src/main/java/org/geysermc/geyser/inventory/item/BannerPattern.java b/core/src/main/java/org/geysermc/geyser/inventory/item/BannerPattern.java
index 442690d7d..743fbdc7e 100644
--- a/core/src/main/java/org/geysermc/geyser/inventory/item/BannerPattern.java
+++ b/core/src/main/java/org/geysermc/geyser/inventory/item/BannerPattern.java
@@ -26,7 +26,9 @@
package org.geysermc.geyser.inventory.item;
import lombok.Getter;
+import net.kyori.adventure.key.Key;
import org.checkerframework.checker.nullness.qual.Nullable;
+import org.geysermc.geyser.util.MinecraftKey;
import java.util.Locale;
@@ -72,21 +74,23 @@ public enum BannerPattern {
SKULL("sku"),
FLOWER("flo"),
MOJANG("moj"),
- PIGLIN("pig");
+ PIGLIN("pig"),
+ FLOW("flw"),
+ GUSTER("gus");
private static final BannerPattern[] VALUES = values();
- private final String javaIdentifier;
+ private final Key javaIdentifier;
private final String bedrockIdentifier;
BannerPattern(String bedrockIdentifier) {
- this.javaIdentifier = "minecraft:" + this.name().toLowerCase(Locale.ROOT);
+ this.javaIdentifier = MinecraftKey.key(this.name().toLowerCase(Locale.ROOT));
this.bedrockIdentifier = bedrockIdentifier;
}
- public static @Nullable BannerPattern getByJavaIdentifier(String javaIdentifier) {
+ public static @Nullable BannerPattern getByJavaIdentifier(Key key) {
for (BannerPattern bannerPattern : VALUES) {
- if (bannerPattern.javaIdentifier.equals(javaIdentifier)) {
+ if (bannerPattern.javaIdentifier.equals(key)) {
return bannerPattern;
}
}
diff --git a/core/src/main/java/org/geysermc/geyser/inventory/item/Enchantment.java b/core/src/main/java/org/geysermc/geyser/inventory/item/BedrockEnchantment.java
similarity index 50%
rename from core/src/main/java/org/geysermc/geyser/inventory/item/Enchantment.java
rename to core/src/main/java/org/geysermc/geyser/inventory/item/BedrockEnchantment.java
index 773de29b1..6d3fdbc27 100644
--- a/core/src/main/java/org/geysermc/geyser/inventory/item/Enchantment.java
+++ b/core/src/main/java/org/geysermc/geyser/inventory/item/BedrockEnchantment.java
@@ -25,13 +25,11 @@
package org.geysermc.geyser.inventory.item;
-import lombok.Getter;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.Locale;
-@Getter
-public enum Enchantment {
+public enum BedrockEnchantment {
PROTECTION,
FIRE_PROTECTION,
FEATHER_FALLING,
@@ -69,18 +67,21 @@ public enum Enchantment {
PIERCING,
QUICK_CHARGE,
SOUL_SPEED,
- SWIFT_SNEAK;
+ SWIFT_SNEAK,
+ WIND_BURST,
+ DENSITY,
+ BREACH;
- private static final Enchantment[] VALUES = values();
+ private static final BedrockEnchantment[] VALUES = values();
private final String javaIdentifier;
- Enchantment() {
+ BedrockEnchantment() {
this.javaIdentifier = "minecraft:" + this.name().toLowerCase(Locale.ENGLISH);
}
- public static @Nullable Enchantment getByJavaIdentifier(String javaIdentifier) {
- for (Enchantment enchantment : VALUES) {
+ public static @Nullable BedrockEnchantment getByJavaIdentifier(String javaIdentifier) {
+ for (BedrockEnchantment enchantment : VALUES) {
if (enchantment.javaIdentifier.equals(javaIdentifier) || enchantment.name().toLowerCase(Locale.ENGLISH).equalsIgnoreCase(javaIdentifier)) {
return enchantment;
}
@@ -88,88 +89,10 @@ public enum Enchantment {
return null;
}
- public static @Nullable Enchantment getByBedrockId(int bedrockId) {
+ public static @Nullable BedrockEnchantment getByBedrockId(int bedrockId) {
if (bedrockId >= 0 && bedrockId < VALUES.length) {
return VALUES[bedrockId];
}
return null;
}
-
- /**
- * Enchantments classified by their Java index
- */
- public enum JavaEnchantment {
- PROTECTION,
- FIRE_PROTECTION,
- FEATHER_FALLING,
- BLAST_PROTECTION,
- PROJECTILE_PROTECTION,
- RESPIRATION,
- AQUA_AFFINITY,
- THORNS,
- DEPTH_STRIDER,
- FROST_WALKER,
- BINDING_CURSE,
- SOUL_SPEED,
- SWIFT_SNEAK,
- SHARPNESS,
- SMITE,
- BANE_OF_ARTHROPODS,
- KNOCKBACK,
- FIRE_ASPECT,
- LOOTING,
- SWEEPING_EDGE,
- EFFICIENCY,
- SILK_TOUCH,
- UNBREAKING,
- FORTUNE,
- POWER,
- PUNCH,
- FLAME,
- INFINITY,
- LUCK_OF_THE_SEA,
- LURE,
- LOYALTY,
- IMPALING,
- RIPTIDE,
- CHANNELING,
- MULTISHOT,
- QUICK_CHARGE,
- PIERCING,
- DENSITY,
- BREACH,
- WIND_BURST,
- MENDING,
- VANISHING_CURSE;
-
- private static final JavaEnchantment[] VALUES = JavaEnchantment.values();
-
- public static JavaEnchantment of(int index) {
- return VALUES[index];
- }
-
- /**
- * A list of all enchantment Java identifiers for use with command suggestions.
- */
- public static final String[] ALL_JAVA_IDENTIFIERS;
-
- public static @Nullable JavaEnchantment getByJavaIdentifier(String javaIdentifier) {
- if (!javaIdentifier.startsWith("minecraft:")) {
- javaIdentifier = "minecraft:" + javaIdentifier;
- }
- for (int i = 0; i < ALL_JAVA_IDENTIFIERS.length; i++) {
- if (ALL_JAVA_IDENTIFIERS[i].equalsIgnoreCase(javaIdentifier)) {
- return VALUES[i];
- }
- }
- return null;
- }
-
- static {
- ALL_JAVA_IDENTIFIERS = new String[VALUES.length];
- for (int i = 0; i < ALL_JAVA_IDENTIFIERS.length; i++) {
- ALL_JAVA_IDENTIFIERS[i] = "minecraft:" + VALUES[i].name().toLowerCase(Locale.ENGLISH);
- }
- }
- }
}
diff --git a/core/src/main/java/org/geysermc/geyser/inventory/item/Potion.java b/core/src/main/java/org/geysermc/geyser/inventory/item/Potion.java
index cf3a37afd..129c365a9 100644
--- a/core/src/main/java/org/geysermc/geyser/inventory/item/Potion.java
+++ b/core/src/main/java/org/geysermc/geyser/inventory/item/Potion.java
@@ -25,70 +25,90 @@
package org.geysermc.geyser.inventory.item;
-import it.unimi.dsi.fastutil.ints.Int2ObjectMaps;
import lombok.Getter;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.PotionContents;
+import java.util.Collections;
import java.util.Locale;
@Getter
public enum Potion {
- WATER(0),
- MUNDANE(1),
- THICK(3),
- AWKWARD(4),
- NIGHT_VISION(5),
- LONG_NIGHT_VISION(6),
- INVISIBILITY(7),
- LONG_INVISIBILITY(8),
- LEAPING(9),
- LONG_LEAPING(10),
- STRONG_LEAPING(11),
- FIRE_RESISTANCE(12),
- LONG_FIRE_RESISTANCE(13),
- SWIFTNESS(14),
- LONG_SWIFTNESS(15),
- STRONG_SWIFTNESS(16),
- SLOWNESS(17),
- LONG_SLOWNESS(18),
- STRONG_SLOWNESS(42),
- TURTLE_MASTER(37),
- LONG_TURTLE_MASTER(38),
- STRONG_TURTLE_MASTER(39),
- WATER_BREATHING(19),
- LONG_WATER_BREATHING(20),
- HEALING(21),
- STRONG_HEALING(22),
- HARMING(23),
- STRONG_HARMING(24),
- POISON(25),
- LONG_POISON(26),
- STRONG_POISON(27),
- REGENERATION(28),
- LONG_REGENERATION(29),
- STRONG_REGENERATION(30),
- STRENGTH(31),
- LONG_STRENGTH(32),
- STRONG_STRENGTH(33),
- WEAKNESS(34),
- LONG_WEAKNESS(35),
- LUCK(2), //does not exist
- SLOW_FALLING(40),
- LONG_SLOW_FALLING(41);
+ WATER(0, ArrowParticleColors.NONE),
+ MUNDANE(1, ArrowParticleColors.NONE), // 2 is extended?
+ THICK(3, ArrowParticleColors.NONE),
+ AWKWARD(4, ArrowParticleColors.NONE),
+ NIGHT_VISION(5, ArrowParticleColors.NIGHT_VISION),
+ LONG_NIGHT_VISION(6, ArrowParticleColors.NIGHT_VISION),
+ INVISIBILITY(7, ArrowParticleColors.INVISIBILITY),
+ LONG_INVISIBILITY(8, ArrowParticleColors.INVISIBILITY),
+ LEAPING(9, ArrowParticleColors.LEAPING),
+ LONG_LEAPING(10, ArrowParticleColors.LEAPING),
+ STRONG_LEAPING(11, ArrowParticleColors.LEAPING),
+ FIRE_RESISTANCE(12, ArrowParticleColors.FIRE_RESISTANCE),
+ LONG_FIRE_RESISTANCE(13, ArrowParticleColors.FIRE_RESISTANCE),
+ SWIFTNESS(14, ArrowParticleColors.SWIFTNESS),
+ LONG_SWIFTNESS(15, ArrowParticleColors.SWIFTNESS),
+ STRONG_SWIFTNESS(16, ArrowParticleColors.SWIFTNESS),
+ SLOWNESS(17, ArrowParticleColors.SLOWNESS),
+ LONG_SLOWNESS(18, ArrowParticleColors.SLOWNESS),
+ STRONG_SLOWNESS(42, ArrowParticleColors.SLOWNESS),
+ TURTLE_MASTER(37, ArrowParticleColors.TURTLE_MASTER),
+ LONG_TURTLE_MASTER(38, ArrowParticleColors.TURTLE_MASTER),
+ STRONG_TURTLE_MASTER(39, ArrowParticleColors.TURTLE_MASTER),
+ WATER_BREATHING(19, ArrowParticleColors.WATER_BREATHING),
+ LONG_WATER_BREATHING(20, ArrowParticleColors.WATER_BREATHING),
+ HEALING(21, ArrowParticleColors.HEALING),
+ STRONG_HEALING(22, ArrowParticleColors.HEALING),
+ HARMING(23, ArrowParticleColors.HARMING),
+ STRONG_HARMING(24, ArrowParticleColors.HARMING),
+ POISON(25, ArrowParticleColors.POISON),
+ LONG_POISON(26, ArrowParticleColors.POISON),
+ STRONG_POISON(27, ArrowParticleColors.POISON),
+ REGENERATION(28, ArrowParticleColors.REGENERATION),
+ LONG_REGENERATION(29, ArrowParticleColors.REGENERATION),
+ STRONG_REGENERATION(30, ArrowParticleColors.REGENERATION),
+ STRENGTH(31, ArrowParticleColors.STRENGTH),
+ LONG_STRENGTH(32, ArrowParticleColors.STRENGTH),
+ STRONG_STRENGTH(33, ArrowParticleColors.STRENGTH),
+ WEAKNESS(34, ArrowParticleColors.WEAKNESS),
+ LONG_WEAKNESS(35, ArrowParticleColors.WEAKNESS),
+ LUCK(2, ArrowParticleColors.NONE), // does not exist in Bedrock
+ SLOW_FALLING(40, ArrowParticleColors.SLOW_FALLING),
+ LONG_SLOW_FALLING(41, ArrowParticleColors.SLOW_FALLING),
+ WIND_CHARGING(43, ArrowParticleColors.WIND_CHARGING),
+ WEAVING(44, ArrowParticleColors.WEAVING),
+ OOZING(45, ArrowParticleColors.OOZING),
+ INFESTATION(46, ArrowParticleColors.INFESTATION);
public static final Potion[] VALUES = values();
private final String javaIdentifier;
private final short bedrockId;
+ private final int javaColor;
- Potion(int bedrockId) {
+ Potion(int bedrockId, int javaColor) {
this.javaIdentifier = "minecraft:" + this.name().toLowerCase(Locale.ENGLISH);
this.bedrockId = (short) bedrockId;
+ this.javaColor = javaColor;
+ }
+
+ public int tippedArrowId() {
+ // +1 likely to offset 0 as nothing?
+ return this.bedrockId + 1;
}
public PotionContents toComponent() {
- return new PotionContents(this.ordinal(), -1, Int2ObjectMaps.emptyMap());
+ return new PotionContents(this.ordinal(), -1, Collections.emptyList());
+ }
+
+ public static Potion getByJavaIdentifier(String javaIdentifier) {
+ for (Potion potion : VALUES) {
+ if (potion.javaIdentifier.equals(javaIdentifier)) {
+ return potion;
+ }
+ }
+ return null;
}
public static @Nullable Potion getByJavaId(int javaId) {
@@ -106,4 +126,44 @@ public enum Potion {
}
return null;
}
+
+ public static @Nullable Potion getByTippedArrowDamage(int bedrockId) {
+ return getByBedrockId(bedrockId - 1);
+ }
+
+ public static byte toTippedArrowId(int javaParticleColor) {
+ for (Potion potion : VALUES) {
+ if (potion.javaColor == javaParticleColor) {
+ return (byte) (potion.bedrockId + 1);
+ }
+ }
+ return (byte) 0;
+ }
+
+ /**
+ * For tipped arrow usage
+ */
+ private static final class ArrowParticleColors {
+ static final int NONE = 1;
+ static final int NIGHT_VISION = 2039713;
+ static final int INVISIBILITY = 8356754;
+ static final int LEAPING = 2293580;
+ static final int FIRE_RESISTANCE = 14981690;
+ static final int SWIFTNESS = 8171462;
+ static final int SLOWNESS = 5926017;
+ static final int TURTLE_MASTER = 7691106;
+ static final int WATER_BREATHING = 3035801;
+ static final int HEALING = 16262179;
+ static final int HARMING = 4393481;
+ static final int POISON = 5149489;
+ static final int REGENERATION = 13458603;
+ static final int STRENGTH = 9643043;
+ static final int WEAKNESS = 4738376;
+ static final int LUCK = 3381504;
+ static final int SLOW_FALLING = 16773073;
+ static final int WIND_CHARGING = 12438015;
+ static final int WEAVING = 7891290;
+ static final int OOZING = 10092451;
+ static final int INFESTATION = 9214860;
+ }
}
diff --git a/core/src/main/java/org/geysermc/geyser/inventory/item/StoredItemMappings.java b/core/src/main/java/org/geysermc/geyser/inventory/item/StoredItemMappings.java
index 0305df685..05f6ba6cc 100644
--- a/core/src/main/java/org/geysermc/geyser/inventory/item/StoredItemMappings.java
+++ b/core/src/main/java/org/geysermc/geyser/inventory/item/StoredItemMappings.java
@@ -42,6 +42,7 @@ import java.util.Map;
public class StoredItemMappings {
private final ItemMapping banner;
private final ItemMapping barrier;
+ private final ItemMapping bow;
private final ItemMapping compass;
private final ItemMapping crossbow;
private final ItemMapping egg;
@@ -57,6 +58,7 @@ public class StoredItemMappings {
public StoredItemMappings(Map itemMappings) {
this.banner = load(itemMappings, Items.WHITE_BANNER); // As of 1.17.10, all banners have the same Bedrock ID
this.barrier = load(itemMappings, Items.BARRIER);
+ this.bow = load(itemMappings, Items.BOW);
this.compass = load(itemMappings, Items.COMPASS);
this.crossbow = load(itemMappings, Items.CROSSBOW);
this.egg = load(itemMappings, Items.EGG);
diff --git a/core/src/main/java/org/geysermc/geyser/inventory/item/TippedArrowPotion.java b/core/src/main/java/org/geysermc/geyser/inventory/item/TippedArrowPotion.java
deleted file mode 100644
index ec6b10ec8..000000000
--- a/core/src/main/java/org/geysermc/geyser/inventory/item/TippedArrowPotion.java
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * 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.inventory.item;
-
-import lombok.Getter;
-import org.checkerframework.checker.nullness.qual.Nullable;
-
-import java.util.Locale;
-
-/**
- * Potion identifiers and their respective Bedrock IDs used with arrows.
- * See here
- */
-@Getter
-public enum TippedArrowPotion {
- WATER(-1, ArrowParticleColors.NONE), // Guessing this based off of the Potion enum. TODO merge?
- MUNDANE(2, ArrowParticleColors.NONE), // 3 is extended?
- THICK(4, ArrowParticleColors.NONE),
- AWKWARD(5, ArrowParticleColors.NONE),
- NIGHT_VISION(6, ArrowParticleColors.NIGHT_VISION),
- LONG_NIGHT_VISION(7, ArrowParticleColors.NIGHT_VISION),
- INVISIBILITY(8, ArrowParticleColors.INVISIBILITY),
- LONG_INVISIBILITY(9, ArrowParticleColors.INVISIBILITY),
- LEAPING(10, ArrowParticleColors.LEAPING),
- LONG_LEAPING(11, ArrowParticleColors.LEAPING),
- STRONG_LEAPING(12, ArrowParticleColors.LEAPING),
- FIRE_RESISTANCE(13, ArrowParticleColors.FIRE_RESISTANCE),
- LONG_FIRE_RESISTANCE(14, ArrowParticleColors.FIRE_RESISTANCE),
- SWIFTNESS(15, ArrowParticleColors.SWIFTNESS),
- LONG_SWIFTNESS(16, ArrowParticleColors.SWIFTNESS),
- STRONG_SWIFTNESS(17, ArrowParticleColors.SWIFTNESS),
- SLOWNESS(18, ArrowParticleColors.SLOWNESS),
- LONG_SLOWNESS(19, ArrowParticleColors.SLOWNESS),
- STRONG_SLOWNESS(43, ArrowParticleColors.SLOWNESS),
- WATER_BREATHING(20, ArrowParticleColors.WATER_BREATHING),
- LONG_WATER_BREATHING(21, ArrowParticleColors.WATER_BREATHING),
- HEALING(22, ArrowParticleColors.HEALING),
- STRONG_HEALING(23, ArrowParticleColors.HEALING),
- HARMING(24, ArrowParticleColors.HARMING),
- STRONG_HARMING(25, ArrowParticleColors.HARMING),
- POISON(26, ArrowParticleColors.POISON),
- LONG_POISON(27, ArrowParticleColors.POISON),
- STRONG_POISON(28, ArrowParticleColors.POISON),
- REGENERATION(29, ArrowParticleColors.REGENERATION),
- LONG_REGENERATION(30, ArrowParticleColors.REGENERATION),
- STRONG_REGENERATION(31, ArrowParticleColors.REGENERATION),
- STRENGTH(32, ArrowParticleColors.STRENGTH),
- LONG_STRENGTH(33, ArrowParticleColors.STRENGTH),
- STRONG_STRENGTH(34, ArrowParticleColors.STRENGTH),
- WEAKNESS(35, ArrowParticleColors.WEAKNESS),
- LONG_WEAKNESS(36, ArrowParticleColors.WEAKNESS),
- LUCK(2, ArrowParticleColors.NONE), // does not exist in Bedrock
- TURTLE_MASTER(38, ArrowParticleColors.TURTLE_MASTER),
- LONG_TURTLE_MASTER(39, ArrowParticleColors.TURTLE_MASTER),
- STRONG_TURTLE_MASTER(40, ArrowParticleColors.TURTLE_MASTER),
- SLOW_FALLING(41, ArrowParticleColors.SLOW_FALLING),
- LONG_SLOW_FALLING(42, ArrowParticleColors.SLOW_FALLING);
-
- private static final TippedArrowPotion[] VALUES = values();
-
- private final String javaIdentifier;
- private final short bedrockId;
- /**
- * The Java color associated with this ID.
- * Used for looking up Java arrow color entity metadata as Bedrock potion IDs, which is what is used for entities in Bedrock
- */
- private final int javaColor;
-
- TippedArrowPotion(int bedrockId, ArrowParticleColors arrowParticleColor) {
- this.javaIdentifier = "minecraft:" + this.name().toLowerCase(Locale.ENGLISH);
- this.bedrockId = (short) bedrockId;
- this.javaColor = arrowParticleColor.getColor();
- }
-
- public static TippedArrowPotion of(int id) {
- return VALUES[id];
- }
-
- public static @Nullable TippedArrowPotion getByBedrockId(int bedrockId) {
- for (TippedArrowPotion potion : VALUES) {
- if (potion.bedrockId == bedrockId) {
- return potion;
- }
- }
- return null;
- }
-
- /**
- * @param color the potion color to look up
- * @return the tipped arrow potion that most closely resembles that color.
- */
- public static @Nullable TippedArrowPotion getByJavaColor(int color) {
- for (TippedArrowPotion potion : VALUES) {
- if (potion.javaColor == color) {
- return potion;
- }
- }
- return null;
- }
-
- private enum ArrowParticleColors {
- NONE(-1),
- NIGHT_VISION(2039713),
- INVISIBILITY(8356754),
- LEAPING(2293580),
- FIRE_RESISTANCE(14981690),
- SWIFTNESS(8171462),
- SLOWNESS(5926017),
- TURTLE_MASTER(7691106),
- WATER_BREATHING(3035801),
- HEALING(16262179),
- HARMING(4393481),
- POISON(5149489),
- REGENERATION(13458603),
- STRENGTH(9643043),
- WEAKNESS(4738376),
- LUCK(3381504),
- SLOW_FALLING(16773073);
-
- @Getter
- private final int color;
-
- ArrowParticleColors(int color) {
- this.color = color;
- }
- }
-}
diff --git a/core/src/main/java/org/geysermc/geyser/inventory/recipe/GeyserRecipe.java b/core/src/main/java/org/geysermc/geyser/inventory/recipe/GeyserRecipe.java
index 9d98e9fb3..8b7fa9522 100644
--- a/core/src/main/java/org/geysermc/geyser/inventory/recipe/GeyserRecipe.java
+++ b/core/src/main/java/org/geysermc/geyser/inventory/recipe/GeyserRecipe.java
@@ -25,6 +25,9 @@
package org.geysermc.geyser.inventory.recipe;
+import org.checkerframework.checker.nullness.qual.Nullable;
+import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack;
+
/**
* A more compact version of {@link org.geysermc.mcprotocollib.protocol.data.game.recipe.Recipe}.
*/
@@ -33,4 +36,7 @@ public interface GeyserRecipe {
* Whether the recipe is flexible or not in which items can be placed where.
*/
boolean isShaped();
+
+ @Nullable
+ ItemStack result();
}
diff --git a/core/src/main/java/org/geysermc/geyser/inventory/recipe/TrimRecipe.java b/core/src/main/java/org/geysermc/geyser/inventory/recipe/TrimRecipe.java
index 37eb905a4..8289813a4 100644
--- a/core/src/main/java/org/geysermc/geyser/inventory/recipe/TrimRecipe.java
+++ b/core/src/main/java/org/geysermc/geyser/inventory/recipe/TrimRecipe.java
@@ -47,7 +47,7 @@ public final class TrimRecipe {
public static final ItemDescriptorWithCount TEMPLATE = tagDescriptor("minecraft:trim_templates");
public static TrimMaterial readTrimMaterial(GeyserSession session, RegistryEntry entry) {
- String key = stripNamespace(entry.getId());
+ String key = entry.getId().asMinimalString();
// Color is used when hovering over the item
// Find the nearest legacy color from the RGB Java gives us to work with
@@ -67,7 +67,7 @@ public final class TrimRecipe {
}
public static TrimPattern readTrimPattern(GeyserSession session, RegistryEntry entry) {
- String key = stripNamespace(entry.getId());
+ String key = entry.getId().asMinimalString();
String itemIdentifier = entry.getData().getString("template_item");
ItemMapping itemMapping = session.getItemMappings().getMapping(itemIdentifier);
@@ -78,15 +78,6 @@ public final class TrimRecipe {
return new TrimPattern(itemMapping.getBedrockIdentifier(), key);
}
- // TODO find a good place for a stripNamespace util method
- private static String stripNamespace(String identifier) {
- int i = identifier.indexOf(':');
- if (i >= 0) {
- return identifier.substring(i + 1);
- }
- return identifier;
- }
-
private TrimRecipe() {
//no-op
}
diff --git a/core/src/main/java/org/geysermc/geyser/inventory/updater/AnvilInventoryUpdater.java b/core/src/main/java/org/geysermc/geyser/inventory/updater/AnvilInventoryUpdater.java
index d6a0d922b..c3ac73372 100644
--- a/core/src/main/java/org/geysermc/geyser/inventory/updater/AnvilInventoryUpdater.java
+++ b/core/src/main/java/org/geysermc/geyser/inventory/updater/AnvilInventoryUpdater.java
@@ -26,7 +26,6 @@
package org.geysermc.geyser.inventory.updater;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
-import it.unimi.dsi.fastutil.objects.Object2IntMaps;
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
import net.kyori.adventure.text.Component;
import org.cloudburstmc.nbt.NbtMap;
@@ -38,10 +37,9 @@ import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.inventory.AnvilContainer;
import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.inventory.Inventory;
-import org.geysermc.geyser.inventory.item.Enchantment.JavaEnchantment;
+import org.geysermc.geyser.inventory.item.BedrockEnchantment;
+import org.geysermc.geyser.item.enchantment.Enchantment;
import org.geysermc.geyser.item.Items;
-import org.geysermc.geyser.registry.Registries;
-import org.geysermc.geyser.registry.type.EnchantmentData;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.inventory.InventoryTranslator;
import org.geysermc.geyser.translator.text.MessageTranslator;
@@ -307,22 +305,22 @@ public class AnvilInventoryUpdater extends InventoryUpdater {
*/
private int calcMergeEnchantmentCost(GeyserSession session, GeyserItemStack input, GeyserItemStack material, boolean bedrock) {
boolean hasCompatible = false;
- Object2IntMap combinedEnchantments = getEnchantments(input);
+ Object2IntMap combinedEnchantments = getEnchantments(session, input);
int cost = 0;
- for (Object2IntMap.Entry entry : getEnchantments(material).object2IntEntrySet()) {
- JavaEnchantment enchantment = entry.getKey();
- EnchantmentData data = Registries.ENCHANTMENTS.get(enchantment);
- if (data == null) {
- GeyserImpl.getInstance().getLogger().debug("Java enchantment not in registry: " + enchantment);
- continue;
- }
+ for (Object2IntMap.Entry entry : getEnchantments(session, material).object2IntEntrySet()) {
+ Enchantment enchantment = entry.getKey();
- boolean canApply = isEnchantedBook(input) || data.validItems().contains(input.getJavaId());
- for (JavaEnchantment incompatible : data.incompatibleEnchantments()) {
- if (combinedEnchantments.containsKey(incompatible)) {
- canApply = false;
- if (!bedrock) {
- cost++;
+ boolean canApply = isEnchantedBook(input) || session.getTagCache().is(enchantment.supportedItems(), input);
+ var exclusiveSet = enchantment.exclusiveSet();
+ if (exclusiveSet != null) {
+ int[] incompatibleEnchantments = session.getTagCache().get(exclusiveSet);
+ for (int i : incompatibleEnchantments) {
+ Enchantment incompatible = session.getRegistryCache().enchantments().byId(i);
+ if (combinedEnchantments.containsKey(incompatible)) {
+ canApply = false;
+ if (!bedrock) {
+ cost++;
+ }
}
}
}
@@ -334,12 +332,12 @@ public class AnvilInventoryUpdater extends InventoryUpdater {
newLevel++;
}
newLevel = Math.max(currentLevel, newLevel);
- if (newLevel > data.maxLevel()) {
- newLevel = data.maxLevel();
+ if (newLevel > enchantment.maxLevel()) {
+ newLevel = enchantment.maxLevel();
}
combinedEnchantments.put(enchantment, newLevel);
- int rarityMultiplier = data.rarityMultiplier();
+ int rarityMultiplier = enchantment.anvilCost();
if (isEnchantedBook(material) && rarityMultiplier > 1) {
rarityMultiplier /= 2;
}
@@ -347,11 +345,11 @@ public class AnvilInventoryUpdater extends InventoryUpdater {
if (newLevel > currentLevel) {
hasCompatible = true;
}
- if (enchantment == JavaEnchantment.IMPALING) {
+ if (enchantment.bedrockEnchantment() == BedrockEnchantment.IMPALING) {
// Multiplier is halved on Bedrock for some reason
rarityMultiplier /= 2;
- } else if (enchantment == JavaEnchantment.SWEEPING_EDGE) {
- // Doesn't exist on Bedrock
+ } else if (enchantment.bedrockEnchantment() == null) {
+ // Whatever this is, doesn't exist on Bedrock
rarityMultiplier = 0;
}
cost += rarityMultiplier * (newLevel - currentLevel);
@@ -368,7 +366,7 @@ public class AnvilInventoryUpdater extends InventoryUpdater {
return cost;
}
- private Object2IntMap getEnchantments(GeyserItemStack itemStack) {
+ private Object2IntMap getEnchantments(GeyserSession session, GeyserItemStack itemStack) {
ItemEnchantments enchantmentComponent;
if (isEnchantedBook(itemStack)) {
enchantmentComponent = itemStack.getComponent(DataComponentType.STORED_ENCHANTMENTS);
@@ -376,9 +374,9 @@ public class AnvilInventoryUpdater extends InventoryUpdater {
enchantmentComponent = itemStack.getComponent(DataComponentType.ENCHANTMENTS);
}
if (enchantmentComponent != null) {
- Object2IntMap enchantments = new Object2IntOpenHashMap<>();
+ Object2IntMap enchantments = new Object2IntOpenHashMap<>();
for (Map.Entry entry : enchantmentComponent.getEnchantments().entrySet()) {
- JavaEnchantment enchantment = JavaEnchantment.of(entry.getKey());
+ Enchantment enchantment = session.getRegistryCache().enchantments().byId(entry.getKey());
if (enchantment == null) {
GeyserImpl.getInstance().getLogger().debug("Unknown Java enchantment in anvil: " + entry.getKey());
continue;
diff --git a/core/src/main/java/org/geysermc/geyser/item/Items.java b/core/src/main/java/org/geysermc/geyser/item/Items.java
index f13330700..1ddd14982 100644
--- a/core/src/main/java/org/geysermc/geyser/item/Items.java
+++ b/core/src/main/java/org/geysermc/geyser/item/Items.java
@@ -27,10 +27,9 @@ package org.geysermc.geyser.item;
import org.geysermc.geyser.item.components.ToolTier;
import org.geysermc.geyser.item.type.*;
+import org.geysermc.geyser.level.block.Blocks;
import org.geysermc.geyser.registry.Registries;
-import java.util.Collections;
-
import static org.geysermc.geyser.item.type.Item.builder;
/**
@@ -39,770 +38,770 @@ import static org.geysermc.geyser.item.type.Item.builder;
@SuppressWarnings("unused")
public final class Items {
public static final Item AIR = register(new Item("air", builder()));
- public static final Item STONE = register(new BlockItem("stone", builder()));
- public static final Item GRANITE = register(new BlockItem("granite", builder()));
- public static final Item POLISHED_GRANITE = register(new BlockItem("polished_granite", builder()));
- public static final Item DIORITE = register(new BlockItem("diorite", builder()));
- public static final Item POLISHED_DIORITE = register(new BlockItem("polished_diorite", builder()));
- public static final Item ANDESITE = register(new BlockItem("andesite", builder()));
- public static final Item POLISHED_ANDESITE = register(new BlockItem("polished_andesite", builder()));
- public static final Item DEEPSLATE = register(new BlockItem("deepslate", builder()));
- public static final Item COBBLED_DEEPSLATE = register(new BlockItem("cobbled_deepslate", builder()));
- public static final Item POLISHED_DEEPSLATE = register(new BlockItem("polished_deepslate", builder()));
- public static final Item CALCITE = register(new BlockItem("calcite", builder()));
- public static final Item TUFF = register(new BlockItem("tuff", builder()));
- public static final Item TUFF_SLAB = register(new BlockItem("tuff_slab", builder()));
- public static final Item TUFF_STAIRS = register(new BlockItem("tuff_stairs", builder()));
- public static final Item TUFF_WALL = register(new BlockItem("tuff_wall", builder()));
- public static final Item CHISELED_TUFF = register(new BlockItem("chiseled_tuff", builder()));
- public static final Item POLISHED_TUFF = register(new BlockItem("polished_tuff", builder()));
- public static final Item POLISHED_TUFF_SLAB = register(new BlockItem("polished_tuff_slab", builder()));
- public static final Item POLISHED_TUFF_STAIRS = register(new BlockItem("polished_tuff_stairs", builder()));
- public static final Item POLISHED_TUFF_WALL = register(new BlockItem("polished_tuff_wall", builder()));
- public static final Item TUFF_BRICKS = register(new BlockItem("tuff_bricks", builder()));
- public static final Item TUFF_BRICK_SLAB = register(new BlockItem("tuff_brick_slab", builder()));
- public static final Item TUFF_BRICK_STAIRS = register(new BlockItem("tuff_brick_stairs", builder()));
- public static final Item TUFF_BRICK_WALL = register(new BlockItem("tuff_brick_wall", builder()));
- public static final Item CHISELED_TUFF_BRICKS = register(new BlockItem("chiseled_tuff_bricks", builder()));
- public static final Item DRIPSTONE_BLOCK = register(new BlockItem("dripstone_block", builder()));
- public static final Item GRASS_BLOCK = register(new BlockItem("grass_block", builder()));
- public static final Item DIRT = register(new BlockItem("dirt", builder()));
- public static final Item COARSE_DIRT = register(new BlockItem("coarse_dirt", builder()));
- public static final Item PODZOL = register(new BlockItem("podzol", builder()));
- public static final Item ROOTED_DIRT = register(new BlockItem("rooted_dirt", builder()));
- public static final Item MUD = register(new BlockItem("mud", builder()));
- public static final Item CRIMSON_NYLIUM = register(new BlockItem("crimson_nylium", builder()));
- public static final Item WARPED_NYLIUM = register(new BlockItem("warped_nylium", builder()));
- public static final Item COBBLESTONE = register(new BlockItem("cobblestone", builder()));
- public static final Item OAK_PLANKS = register(new BlockItem("oak_planks", builder()));
- public static final Item SPRUCE_PLANKS = register(new BlockItem("spruce_planks", builder()));
- public static final Item BIRCH_PLANKS = register(new BlockItem("birch_planks", builder()));
- public static final Item JUNGLE_PLANKS = register(new BlockItem("jungle_planks", builder()));
- public static final Item ACACIA_PLANKS = register(new BlockItem("acacia_planks", builder()));
- public static final Item CHERRY_PLANKS = register(new BlockItem("cherry_planks", builder()));
- public static final Item DARK_OAK_PLANKS = register(new BlockItem("dark_oak_planks", builder()));
- public static final Item MANGROVE_PLANKS = register(new BlockItem("mangrove_planks", builder()));
- public static final Item BAMBOO_PLANKS = register(new BlockItem("bamboo_planks", builder()));
- public static final Item CRIMSON_PLANKS = register(new BlockItem("crimson_planks", builder()));
- public static final Item WARPED_PLANKS = register(new BlockItem("warped_planks", builder()));
- public static final Item BAMBOO_MOSAIC = register(new BlockItem("bamboo_mosaic", builder()));
- public static final Item OAK_SAPLING = register(new BlockItem("oak_sapling", builder()));
- public static final Item SPRUCE_SAPLING = register(new BlockItem("spruce_sapling", builder()));
- public static final Item BIRCH_SAPLING = register(new BlockItem("birch_sapling", builder()));
- public static final Item JUNGLE_SAPLING = register(new BlockItem("jungle_sapling", builder()));
- public static final Item ACACIA_SAPLING = register(new BlockItem("acacia_sapling", builder()));
- public static final Item CHERRY_SAPLING = register(new BlockItem("cherry_sapling", builder()));
- public static final Item DARK_OAK_SAPLING = register(new BlockItem("dark_oak_sapling", builder()));
- public static final Item MANGROVE_PROPAGULE = register(new BlockItem("mangrove_propagule", builder()));
- public static final Item BEDROCK = register(new BlockItem("bedrock", builder()));
- public static final Item SAND = register(new BlockItem("sand", builder()));
- public static final Item SUSPICIOUS_SAND = register(new BlockItem("suspicious_sand", builder()));
- public static final Item SUSPICIOUS_GRAVEL = register(new BlockItem("suspicious_gravel", builder()));
- public static final Item RED_SAND = register(new BlockItem("red_sand", builder()));
- public static final Item GRAVEL = register(new BlockItem("gravel", builder()));
- public static final Item COAL_ORE = register(new BlockItem("coal_ore", builder()));
- public static final Item DEEPSLATE_COAL_ORE = register(new BlockItem("deepslate_coal_ore", builder()));
- public static final Item IRON_ORE = register(new BlockItem("iron_ore", builder()));
- public static final Item DEEPSLATE_IRON_ORE = register(new BlockItem("deepslate_iron_ore", builder()));
- public static final Item COPPER_ORE = register(new BlockItem("copper_ore", builder()));
- public static final Item DEEPSLATE_COPPER_ORE = register(new BlockItem("deepslate_copper_ore", builder()));
- public static final Item GOLD_ORE = register(new BlockItem("gold_ore", builder()));
- public static final Item DEEPSLATE_GOLD_ORE = register(new BlockItem("deepslate_gold_ore", builder()));
- public static final Item REDSTONE_ORE = register(new BlockItem("redstone_ore", builder()));
- public static final Item DEEPSLATE_REDSTONE_ORE = register(new BlockItem("deepslate_redstone_ore", builder()));
- public static final Item EMERALD_ORE = register(new BlockItem("emerald_ore", builder()));
- public static final Item DEEPSLATE_EMERALD_ORE = register(new BlockItem("deepslate_emerald_ore", builder()));
- public static final Item LAPIS_ORE = register(new BlockItem("lapis_ore", builder()));
- public static final Item DEEPSLATE_LAPIS_ORE = register(new BlockItem("deepslate_lapis_ore", builder()));
- public static final Item DIAMOND_ORE = register(new BlockItem("diamond_ore", builder()));
- public static final Item DEEPSLATE_DIAMOND_ORE = register(new BlockItem("deepslate_diamond_ore", builder()));
- public static final Item NETHER_GOLD_ORE = register(new BlockItem("nether_gold_ore", builder()));
- public static final Item NETHER_QUARTZ_ORE = register(new BlockItem("nether_quartz_ore", builder()));
- public static final Item ANCIENT_DEBRIS = register(new BlockItem("ancient_debris", builder()));
- public static final Item COAL_BLOCK = register(new BlockItem("coal_block", builder()));
- public static final Item RAW_IRON_BLOCK = register(new BlockItem("raw_iron_block", builder()));
- public static final Item RAW_COPPER_BLOCK = register(new BlockItem("raw_copper_block", builder()));
- public static final Item RAW_GOLD_BLOCK = register(new BlockItem("raw_gold_block", builder()));
- public static final Item HEAVY_CORE = register(new BlockItem("heavy_core", builder()));
- public static final Item AMETHYST_BLOCK = register(new BlockItem("amethyst_block", builder()));
- public static final Item BUDDING_AMETHYST = register(new BlockItem("budding_amethyst", builder()));
- public static final Item IRON_BLOCK = register(new BlockItem("iron_block", builder()));
- public static final Item COPPER_BLOCK = register(new BlockItem("copper_block", builder()));
- public static final Item GOLD_BLOCK = register(new BlockItem("gold_block", builder()));
- public static final Item DIAMOND_BLOCK = register(new BlockItem("diamond_block", builder()));
- public static final Item NETHERITE_BLOCK = register(new BlockItem("netherite_block", builder()));
- public static final Item EXPOSED_COPPER = register(new BlockItem("exposed_copper", builder()));
- public static final Item WEATHERED_COPPER = register(new BlockItem("weathered_copper", builder()));
- public static final Item OXIDIZED_COPPER = register(new BlockItem("oxidized_copper", builder()));
- public static final Item CHISELED_COPPER = register(new BlockItem("chiseled_copper", builder()));
- public static final Item EXPOSED_CHISELED_COPPER = register(new BlockItem("exposed_chiseled_copper", builder()));
- public static final Item WEATHERED_CHISELED_COPPER = register(new BlockItem("weathered_chiseled_copper", builder()));
- public static final Item OXIDIZED_CHISELED_COPPER = register(new BlockItem("oxidized_chiseled_copper", builder()));
- public static final Item CUT_COPPER = register(new BlockItem("cut_copper", builder()));
- public static final Item EXPOSED_CUT_COPPER = register(new BlockItem("exposed_cut_copper", builder()));
- public static final Item WEATHERED_CUT_COPPER = register(new BlockItem("weathered_cut_copper", builder()));
- public static final Item OXIDIZED_CUT_COPPER = register(new BlockItem("oxidized_cut_copper", builder()));
- public static final Item CUT_COPPER_STAIRS = register(new BlockItem("cut_copper_stairs", builder()));
- public static final Item EXPOSED_CUT_COPPER_STAIRS = register(new BlockItem("exposed_cut_copper_stairs", builder()));
- public static final Item WEATHERED_CUT_COPPER_STAIRS = register(new BlockItem("weathered_cut_copper_stairs", builder()));
- public static final Item OXIDIZED_CUT_COPPER_STAIRS = register(new BlockItem("oxidized_cut_copper_stairs", builder()));
- public static final Item CUT_COPPER_SLAB = register(new BlockItem("cut_copper_slab", builder()));
- public static final Item EXPOSED_CUT_COPPER_SLAB = register(new BlockItem("exposed_cut_copper_slab", builder()));
- public static final Item WEATHERED_CUT_COPPER_SLAB = register(new BlockItem("weathered_cut_copper_slab", builder()));
- public static final Item OXIDIZED_CUT_COPPER_SLAB = register(new BlockItem("oxidized_cut_copper_slab", builder()));
- public static final Item WAXED_COPPER_BLOCK = register(new BlockItem("waxed_copper_block", builder()));
- public static final Item WAXED_EXPOSED_COPPER = register(new BlockItem("waxed_exposed_copper", builder()));
- public static final Item WAXED_WEATHERED_COPPER = register(new BlockItem("waxed_weathered_copper", builder()));
- public static final Item WAXED_OXIDIZED_COPPER = register(new BlockItem("waxed_oxidized_copper", builder()));
- public static final Item WAXED_CHISELED_COPPER = register(new BlockItem("waxed_chiseled_copper", builder()));
- public static final Item WAXED_EXPOSED_CHISELED_COPPER = register(new BlockItem("waxed_exposed_chiseled_copper", builder()));
- public static final Item WAXED_WEATHERED_CHISELED_COPPER = register(new BlockItem("waxed_weathered_chiseled_copper", builder()));
- public static final Item WAXED_OXIDIZED_CHISELED_COPPER = register(new BlockItem("waxed_oxidized_chiseled_copper", builder()));
- public static final Item WAXED_CUT_COPPER = register(new BlockItem("waxed_cut_copper", builder()));
- public static final Item WAXED_EXPOSED_CUT_COPPER = register(new BlockItem("waxed_exposed_cut_copper", builder()));
- public static final Item WAXED_WEATHERED_CUT_COPPER = register(new BlockItem("waxed_weathered_cut_copper", builder()));
- public static final Item WAXED_OXIDIZED_CUT_COPPER = register(new BlockItem("waxed_oxidized_cut_copper", builder()));
- public static final Item WAXED_CUT_COPPER_STAIRS = register(new BlockItem("waxed_cut_copper_stairs", builder()));
- public static final Item WAXED_EXPOSED_CUT_COPPER_STAIRS = register(new BlockItem("waxed_exposed_cut_copper_stairs", builder()));
- public static final Item WAXED_WEATHERED_CUT_COPPER_STAIRS = register(new BlockItem("waxed_weathered_cut_copper_stairs", builder()));
- public static final Item WAXED_OXIDIZED_CUT_COPPER_STAIRS = register(new BlockItem("waxed_oxidized_cut_copper_stairs", builder()));
- public static final Item WAXED_CUT_COPPER_SLAB = register(new BlockItem("waxed_cut_copper_slab", builder()));
- public static final Item WAXED_EXPOSED_CUT_COPPER_SLAB = register(new BlockItem("waxed_exposed_cut_copper_slab", builder()));
- public static final Item WAXED_WEATHERED_CUT_COPPER_SLAB = register(new BlockItem("waxed_weathered_cut_copper_slab", builder()));
- public static final Item WAXED_OXIDIZED_CUT_COPPER_SLAB = register(new BlockItem("waxed_oxidized_cut_copper_slab", builder()));
- public static final Item OAK_LOG = register(new BlockItem("oak_log", builder()));
- public static final Item SPRUCE_LOG = register(new BlockItem("spruce_log", builder()));
- public static final Item BIRCH_LOG = register(new BlockItem("birch_log", builder()));
- public static final Item JUNGLE_LOG = register(new BlockItem("jungle_log", builder()));
- public static final Item ACACIA_LOG = register(new BlockItem("acacia_log", builder()));
- public static final Item CHERRY_LOG = register(new BlockItem("cherry_log", builder()));
- public static final Item DARK_OAK_LOG = register(new BlockItem("dark_oak_log", builder()));
- public static final Item MANGROVE_LOG = register(new BlockItem("mangrove_log", builder()));
- public static final Item MANGROVE_ROOTS = register(new BlockItem("mangrove_roots", builder()));
- public static final Item MUDDY_MANGROVE_ROOTS = register(new BlockItem("muddy_mangrove_roots", builder()));
- public static final Item CRIMSON_STEM = register(new BlockItem("crimson_stem", builder()));
- public static final Item WARPED_STEM = register(new BlockItem("warped_stem", builder()));
- public static final Item BAMBOO_BLOCK = register(new BlockItem("bamboo_block", builder()));
- public static final Item STRIPPED_OAK_LOG = register(new BlockItem("stripped_oak_log", builder()));
- public static final Item STRIPPED_SPRUCE_LOG = register(new BlockItem("stripped_spruce_log", builder()));
- public static final Item STRIPPED_BIRCH_LOG = register(new BlockItem("stripped_birch_log", builder()));
- public static final Item STRIPPED_JUNGLE_LOG = register(new BlockItem("stripped_jungle_log", builder()));
- public static final Item STRIPPED_ACACIA_LOG = register(new BlockItem("stripped_acacia_log", builder()));
- public static final Item STRIPPED_CHERRY_LOG = register(new BlockItem("stripped_cherry_log", builder()));
- public static final Item STRIPPED_DARK_OAK_LOG = register(new BlockItem("stripped_dark_oak_log", builder()));
- public static final Item STRIPPED_MANGROVE_LOG = register(new BlockItem("stripped_mangrove_log", builder()));
- public static final Item STRIPPED_CRIMSON_STEM = register(new BlockItem("stripped_crimson_stem", builder()));
- public static final Item STRIPPED_WARPED_STEM = register(new BlockItem("stripped_warped_stem", builder()));
- public static final Item STRIPPED_OAK_WOOD = register(new BlockItem("stripped_oak_wood", builder()));
- public static final Item STRIPPED_SPRUCE_WOOD = register(new BlockItem("stripped_spruce_wood", builder()));
- public static final Item STRIPPED_BIRCH_WOOD = register(new BlockItem("stripped_birch_wood", builder()));
- public static final Item STRIPPED_JUNGLE_WOOD = register(new BlockItem("stripped_jungle_wood", builder()));
- public static final Item STRIPPED_ACACIA_WOOD = register(new BlockItem("stripped_acacia_wood", builder()));
- public static final Item STRIPPED_CHERRY_WOOD = register(new BlockItem("stripped_cherry_wood", builder()));
- public static final Item STRIPPED_DARK_OAK_WOOD = register(new BlockItem("stripped_dark_oak_wood", builder()));
- public static final Item STRIPPED_MANGROVE_WOOD = register(new BlockItem("stripped_mangrove_wood", builder()));
- public static final Item STRIPPED_CRIMSON_HYPHAE = register(new BlockItem("stripped_crimson_hyphae", builder()));
- public static final Item STRIPPED_WARPED_HYPHAE = register(new BlockItem("stripped_warped_hyphae", builder()));
- public static final Item STRIPPED_BAMBOO_BLOCK = register(new BlockItem("stripped_bamboo_block", builder()));
- public static final Item OAK_WOOD = register(new BlockItem("oak_wood", builder()));
- public static final Item SPRUCE_WOOD = register(new BlockItem("spruce_wood", builder()));
- public static final Item BIRCH_WOOD = register(new BlockItem("birch_wood", builder()));
- public static final Item JUNGLE_WOOD = register(new BlockItem("jungle_wood", builder()));
- public static final Item ACACIA_WOOD = register(new BlockItem("acacia_wood", builder()));
- public static final Item CHERRY_WOOD = register(new BlockItem("cherry_wood", builder()));
- public static final Item DARK_OAK_WOOD = register(new BlockItem("dark_oak_wood", builder()));
- public static final Item MANGROVE_WOOD = register(new BlockItem("mangrove_wood", builder()));
- public static final Item CRIMSON_HYPHAE = register(new BlockItem("crimson_hyphae", builder()));
- public static final Item WARPED_HYPHAE = register(new BlockItem("warped_hyphae", builder()));
- public static final Item OAK_LEAVES = register(new BlockItem("oak_leaves", builder()));
- public static final Item SPRUCE_LEAVES = register(new BlockItem("spruce_leaves", builder()));
- public static final Item BIRCH_LEAVES = register(new BlockItem("birch_leaves", builder()));
- public static final Item JUNGLE_LEAVES = register(new BlockItem("jungle_leaves", builder()));
- public static final Item ACACIA_LEAVES = register(new BlockItem("acacia_leaves", builder()));
- public static final Item CHERRY_LEAVES = register(new BlockItem("cherry_leaves", builder()));
- public static final Item DARK_OAK_LEAVES = register(new BlockItem("dark_oak_leaves", builder()));
- public static final Item MANGROVE_LEAVES = register(new BlockItem("mangrove_leaves", builder()));
- public static final Item AZALEA_LEAVES = register(new BlockItem("azalea_leaves", builder()));
- public static final Item FLOWERING_AZALEA_LEAVES = register(new BlockItem("flowering_azalea_leaves", builder()));
- public static final Item SPONGE = register(new BlockItem("sponge", builder()));
- public static final Item WET_SPONGE = register(new BlockItem("wet_sponge", builder()));
- public static final Item GLASS = register(new BlockItem("glass", builder()));
- public static final Item TINTED_GLASS = register(new BlockItem("tinted_glass", builder()));
- public static final Item LAPIS_BLOCK = register(new BlockItem("lapis_block", builder()));
- public static final Item SANDSTONE = register(new BlockItem("sandstone", builder()));
- public static final Item CHISELED_SANDSTONE = register(new BlockItem("chiseled_sandstone", builder()));
- public static final Item CUT_SANDSTONE = register(new BlockItem("cut_sandstone", builder()));
- public static final Item COBWEB = register(new BlockItem("cobweb", builder()));
- public static final Item SHORT_GRASS = register(new BlockItem("short_grass", builder()));
- public static final Item FERN = register(new BlockItem("fern", builder()));
- public static final Item AZALEA = register(new BlockItem("azalea", builder()));
- public static final Item FLOWERING_AZALEA = register(new BlockItem("flowering_azalea", builder()));
- public static final Item DEAD_BUSH = register(new BlockItem("dead_bush", builder()));
- public static final Item SEAGRASS = register(new BlockItem("seagrass", builder()));
- public static final Item SEA_PICKLE = register(new BlockItem("sea_pickle", builder()));
- public static final Item WHITE_WOOL = register(new BlockItem("white_wool", builder()));
- public static final Item ORANGE_WOOL = register(new BlockItem("orange_wool", builder()));
- public static final Item MAGENTA_WOOL = register(new BlockItem("magenta_wool", builder()));
- public static final Item LIGHT_BLUE_WOOL = register(new BlockItem("light_blue_wool", builder()));
- public static final Item YELLOW_WOOL = register(new BlockItem("yellow_wool", builder()));
- public static final Item LIME_WOOL = register(new BlockItem("lime_wool", builder()));
- public static final Item PINK_WOOL = register(new BlockItem("pink_wool", builder()));
- public static final Item GRAY_WOOL = register(new BlockItem("gray_wool", builder()));
- public static final Item LIGHT_GRAY_WOOL = register(new BlockItem("light_gray_wool", builder()));
- public static final Item CYAN_WOOL = register(new BlockItem("cyan_wool", builder()));
- public static final Item PURPLE_WOOL = register(new BlockItem("purple_wool", builder()));
- public static final Item BLUE_WOOL = register(new BlockItem("blue_wool", builder()));
- public static final Item BROWN_WOOL = register(new BlockItem("brown_wool", builder()));
- public static final Item GREEN_WOOL = register(new BlockItem("green_wool", builder()));
- public static final Item RED_WOOL = register(new BlockItem("red_wool", builder()));
- public static final Item BLACK_WOOL = register(new BlockItem("black_wool", builder()));
- public static final Item DANDELION = register(new BlockItem("dandelion", builder()));
- public static final Item POPPY = register(new BlockItem("poppy", builder()));
- public static final Item BLUE_ORCHID = register(new BlockItem("blue_orchid", builder()));
- public static final Item ALLIUM = register(new BlockItem("allium", builder()));
- public static final Item AZURE_BLUET = register(new BlockItem("azure_bluet", builder()));
- public static final Item RED_TULIP = register(new BlockItem("red_tulip", builder()));
- public static final Item ORANGE_TULIP = register(new BlockItem("orange_tulip", builder()));
- public static final Item WHITE_TULIP = register(new BlockItem("white_tulip", builder()));
- public static final Item PINK_TULIP = register(new BlockItem("pink_tulip", builder()));
- public static final Item OXEYE_DAISY = register(new BlockItem("oxeye_daisy", builder()));
- public static final Item CORNFLOWER = register(new BlockItem("cornflower", builder()));
- public static final Item LILY_OF_THE_VALLEY = register(new BlockItem("lily_of_the_valley", builder()));
- public static final Item WITHER_ROSE = register(new BlockItem("wither_rose", builder()));
- public static final Item TORCHFLOWER = register(new BlockItem("torchflower", builder()));
- public static final Item PITCHER_PLANT = register(new BlockItem("pitcher_plant", builder()));
- public static final Item SPORE_BLOSSOM = register(new BlockItem("spore_blossom", builder()));
- public static final Item BROWN_MUSHROOM = register(new BlockItem("brown_mushroom", builder()));
- public static final Item RED_MUSHROOM = register(new BlockItem("red_mushroom", builder()));
- public static final Item CRIMSON_FUNGUS = register(new BlockItem("crimson_fungus", builder()));
- public static final Item WARPED_FUNGUS = register(new BlockItem("warped_fungus", builder()));
- public static final Item CRIMSON_ROOTS = register(new BlockItem("crimson_roots", builder()));
- public static final Item WARPED_ROOTS = register(new BlockItem("warped_roots", builder()));
- public static final Item NETHER_SPROUTS = register(new BlockItem("nether_sprouts", builder()));
- public static final Item WEEPING_VINES = register(new BlockItem("weeping_vines", builder()));
- public static final Item TWISTING_VINES = register(new BlockItem("twisting_vines", builder()));
- public static final Item SUGAR_CANE = register(new BlockItem("sugar_cane", builder()));
- public static final Item KELP = register(new BlockItem("kelp", builder()));
- public static final Item MOSS_CARPET = register(new BlockItem("moss_carpet", builder()));
- public static final Item PINK_PETALS = register(new BlockItem("pink_petals", builder()));
- public static final Item MOSS_BLOCK = register(new BlockItem("moss_block", builder()));
- public static final Item HANGING_ROOTS = register(new BlockItem("hanging_roots", builder()));
- public static final Item BIG_DRIPLEAF = register(new BlockItem("big_dripleaf", builder()));
- public static final Item SMALL_DRIPLEAF = register(new BlockItem("small_dripleaf", builder()));
- public static final Item BAMBOO = register(new BlockItem("bamboo", builder()));
- public static final Item OAK_SLAB = register(new BlockItem("oak_slab", builder()));
- public static final Item SPRUCE_SLAB = register(new BlockItem("spruce_slab", builder()));
- public static final Item BIRCH_SLAB = register(new BlockItem("birch_slab", builder()));
- public static final Item JUNGLE_SLAB = register(new BlockItem("jungle_slab", builder()));
- public static final Item ACACIA_SLAB = register(new BlockItem("acacia_slab", builder()));
- public static final Item CHERRY_SLAB = register(new BlockItem("cherry_slab", builder()));
- public static final Item DARK_OAK_SLAB = register(new BlockItem("dark_oak_slab", builder()));
- public static final Item MANGROVE_SLAB = register(new BlockItem("mangrove_slab", builder()));
- public static final Item BAMBOO_SLAB = register(new BlockItem("bamboo_slab", builder()));
- public static final Item BAMBOO_MOSAIC_SLAB = register(new BlockItem("bamboo_mosaic_slab", builder()));
- public static final Item CRIMSON_SLAB = register(new BlockItem("crimson_slab", builder()));
- public static final Item WARPED_SLAB = register(new BlockItem("warped_slab", builder()));
- public static final Item STONE_SLAB = register(new BlockItem("stone_slab", builder()));
- public static final Item SMOOTH_STONE_SLAB = register(new BlockItem("smooth_stone_slab", builder()));
- public static final Item SANDSTONE_SLAB = register(new BlockItem("sandstone_slab", builder()));
- public static final Item CUT_SANDSTONE_SLAB = register(new BlockItem("cut_sandstone_slab", builder()));
- public static final Item PETRIFIED_OAK_SLAB = register(new BlockItem("petrified_oak_slab", builder()));
- public static final Item COBBLESTONE_SLAB = register(new BlockItem("cobblestone_slab", builder()));
- public static final Item BRICK_SLAB = register(new BlockItem("brick_slab", builder()));
- public static final Item STONE_BRICK_SLAB = register(new BlockItem("stone_brick_slab", builder()));
- public static final Item MUD_BRICK_SLAB = register(new BlockItem("mud_brick_slab", builder()));
- public static final Item NETHER_BRICK_SLAB = register(new BlockItem("nether_brick_slab", builder()));
- public static final Item QUARTZ_SLAB = register(new BlockItem("quartz_slab", builder()));
- public static final Item RED_SANDSTONE_SLAB = register(new BlockItem("red_sandstone_slab", builder()));
- public static final Item CUT_RED_SANDSTONE_SLAB = register(new BlockItem("cut_red_sandstone_slab", builder()));
- public static final Item PURPUR_SLAB = register(new BlockItem("purpur_slab", builder()));
- public static final Item PRISMARINE_SLAB = register(new BlockItem("prismarine_slab", builder()));
- public static final Item PRISMARINE_BRICK_SLAB = register(new BlockItem("prismarine_brick_slab", builder()));
- public static final Item DARK_PRISMARINE_SLAB = register(new BlockItem("dark_prismarine_slab", builder()));
- public static final Item SMOOTH_QUARTZ = register(new BlockItem("smooth_quartz", builder()));
- public static final Item SMOOTH_RED_SANDSTONE = register(new BlockItem("smooth_red_sandstone", builder()));
- public static final Item SMOOTH_SANDSTONE = register(new BlockItem("smooth_sandstone", builder()));
- public static final Item SMOOTH_STONE = register(new BlockItem("smooth_stone", builder()));
- public static final Item BRICKS = register(new BlockItem("bricks", builder()));
- public static final Item BOOKSHELF = register(new BlockItem("bookshelf", builder()));
- public static final Item CHISELED_BOOKSHELF = register(new BlockItem("chiseled_bookshelf", builder()));
- public static final Item DECORATED_POT = register(new DecoratedPotItem("decorated_pot", builder()));
- public static final Item MOSSY_COBBLESTONE = register(new BlockItem("mossy_cobblestone", builder()));
- public static final Item OBSIDIAN = register(new BlockItem("obsidian", builder()));
- public static final Item TORCH = register(new BlockItem("torch", builder()));
- public static final Item END_ROD = register(new BlockItem("end_rod", builder()));
- public static final Item CHORUS_PLANT = register(new BlockItem("chorus_plant", builder()));
- public static final Item CHORUS_FLOWER = register(new BlockItem("chorus_flower", builder()));
- public static final Item PURPUR_BLOCK = register(new BlockItem("purpur_block", builder()));
- public static final Item PURPUR_PILLAR = register(new BlockItem("purpur_pillar", builder()));
- public static final Item PURPUR_STAIRS = register(new BlockItem("purpur_stairs", builder()));
- public static final Item SPAWNER = register(new BlockItem("spawner", builder()));
- public static final Item CHEST = register(new BlockItem("chest", builder()));
- public static final Item CRAFTING_TABLE = register(new BlockItem("crafting_table", builder()));
- public static final Item FARMLAND = register(new BlockItem("farmland", builder()));
- public static final Item FURNACE = register(new BlockItem("furnace", builder()));
- public static final Item LADDER = register(new BlockItem("ladder", builder()));
- public static final Item COBBLESTONE_STAIRS = register(new BlockItem("cobblestone_stairs", builder()));
- public static final Item SNOW = register(new BlockItem("snow", builder()));
- public static final Item ICE = register(new BlockItem("ice", builder()));
- public static final Item SNOW_BLOCK = register(new BlockItem("snow_block", builder()));
- public static final Item CACTUS = register(new BlockItem("cactus", builder()));
- public static final Item CLAY = register(new BlockItem("clay", builder()));
- public static final Item JUKEBOX = register(new BlockItem("jukebox", builder()));
- public static final Item OAK_FENCE = register(new BlockItem("oak_fence", builder()));
- public static final Item SPRUCE_FENCE = register(new BlockItem("spruce_fence", builder()));
- public static final Item BIRCH_FENCE = register(new BlockItem("birch_fence", builder()));
- public static final Item JUNGLE_FENCE = register(new BlockItem("jungle_fence", builder()));
- public static final Item ACACIA_FENCE = register(new BlockItem("acacia_fence", builder()));
- public static final Item CHERRY_FENCE = register(new BlockItem("cherry_fence", builder()));
- public static final Item DARK_OAK_FENCE = register(new BlockItem("dark_oak_fence", builder()));
- public static final Item MANGROVE_FENCE = register(new BlockItem("mangrove_fence", builder()));
- public static final Item BAMBOO_FENCE = register(new BlockItem("bamboo_fence", builder()));
- public static final Item CRIMSON_FENCE = register(new BlockItem("crimson_fence", builder()));
- public static final Item WARPED_FENCE = register(new BlockItem("warped_fence", builder()));
- public static final Item PUMPKIN = register(new BlockItem("pumpkin", builder()));
- public static final Item CARVED_PUMPKIN = register(new BlockItem("carved_pumpkin", builder()));
- public static final Item JACK_O_LANTERN = register(new BlockItem("jack_o_lantern", builder()));
- public static final Item NETHERRACK = register(new BlockItem("netherrack", builder()));
- public static final Item SOUL_SAND = register(new BlockItem("soul_sand", builder()));
- public static final Item SOUL_SOIL = register(new BlockItem("soul_soil", builder()));
- public static final Item BASALT = register(new BlockItem("basalt", builder()));
- public static final Item POLISHED_BASALT = register(new BlockItem("polished_basalt", builder()));
- public static final Item SMOOTH_BASALT = register(new BlockItem("smooth_basalt", builder()));
- public static final Item SOUL_TORCH = register(new BlockItem("soul_torch", builder()));
- public static final Item GLOWSTONE = register(new BlockItem("glowstone", builder()));
- public static final Item INFESTED_STONE = register(new BlockItem("infested_stone", builder()));
- public static final Item INFESTED_COBBLESTONE = register(new BlockItem("infested_cobblestone", builder()));
- public static final Item INFESTED_STONE_BRICKS = register(new BlockItem("infested_stone_bricks", builder()));
- public static final Item INFESTED_MOSSY_STONE_BRICKS = register(new BlockItem("infested_mossy_stone_bricks", builder()));
- public static final Item INFESTED_CRACKED_STONE_BRICKS = register(new BlockItem("infested_cracked_stone_bricks", builder()));
- public static final Item INFESTED_CHISELED_STONE_BRICKS = register(new BlockItem("infested_chiseled_stone_bricks", builder()));
- public static final Item INFESTED_DEEPSLATE = register(new BlockItem("infested_deepslate", builder()));
- public static final Item STONE_BRICKS = register(new BlockItem("stone_bricks", builder()));
- public static final Item MOSSY_STONE_BRICKS = register(new BlockItem("mossy_stone_bricks", builder()));
- public static final Item CRACKED_STONE_BRICKS = register(new BlockItem("cracked_stone_bricks", builder()));
- public static final Item CHISELED_STONE_BRICKS = register(new BlockItem("chiseled_stone_bricks", builder()));
- public static final Item PACKED_MUD = register(new BlockItem("packed_mud", builder()));
- public static final Item MUD_BRICKS = register(new BlockItem("mud_bricks", builder()));
- public static final Item DEEPSLATE_BRICKS = register(new BlockItem("deepslate_bricks", builder()));
- public static final Item CRACKED_DEEPSLATE_BRICKS = register(new BlockItem("cracked_deepslate_bricks", builder()));
- public static final Item DEEPSLATE_TILES = register(new BlockItem("deepslate_tiles", builder()));
- public static final Item CRACKED_DEEPSLATE_TILES = register(new BlockItem("cracked_deepslate_tiles", builder()));
- public static final Item CHISELED_DEEPSLATE = register(new BlockItem("chiseled_deepslate", builder()));
- public static final Item REINFORCED_DEEPSLATE = register(new BlockItem("reinforced_deepslate", builder()));
- public static final Item BROWN_MUSHROOM_BLOCK = register(new BlockItem("brown_mushroom_block", builder()));
- public static final Item RED_MUSHROOM_BLOCK = register(new BlockItem("red_mushroom_block", builder()));
- public static final Item MUSHROOM_STEM = register(new BlockItem("mushroom_stem", builder()));
- public static final Item IRON_BARS = register(new BlockItem("iron_bars", builder()));
- public static final Item CHAIN = register(new BlockItem("chain", builder()));
- public static final Item GLASS_PANE = register(new BlockItem("glass_pane", builder()));
- public static final Item MELON = register(new BlockItem("melon", builder()));
- public static final Item VINE = register(new BlockItem("vine", builder()));
- public static final Item GLOW_LICHEN = register(new BlockItem("glow_lichen", builder()));
- public static final Item BRICK_STAIRS = register(new BlockItem("brick_stairs", builder()));
- public static final Item STONE_BRICK_STAIRS = register(new BlockItem("stone_brick_stairs", builder()));
- public static final Item MUD_BRICK_STAIRS = register(new BlockItem("mud_brick_stairs", builder()));
- public static final Item MYCELIUM = register(new BlockItem("mycelium", builder()));
- public static final Item LILY_PAD = register(new BlockItem("lily_pad", builder()));
- public static final Item NETHER_BRICKS = register(new BlockItem("nether_bricks", builder()));
- public static final Item CRACKED_NETHER_BRICKS = register(new BlockItem("cracked_nether_bricks", builder()));
- public static final Item CHISELED_NETHER_BRICKS = register(new BlockItem("chiseled_nether_bricks", builder()));
- public static final Item NETHER_BRICK_FENCE = register(new BlockItem("nether_brick_fence", builder()));
- public static final Item NETHER_BRICK_STAIRS = register(new BlockItem("nether_brick_stairs", builder()));
- public static final Item SCULK = register(new BlockItem("sculk", builder()));
- public static final Item SCULK_VEIN = register(new BlockItem("sculk_vein", builder()));
- public static final Item SCULK_CATALYST = register(new BlockItem("sculk_catalyst", builder()));
- public static final Item SCULK_SHRIEKER = register(new BlockItem("sculk_shrieker", builder()));
- public static final Item ENCHANTING_TABLE = register(new BlockItem("enchanting_table", builder()));
- public static final Item END_PORTAL_FRAME = register(new BlockItem("end_portal_frame", builder()));
- public static final Item END_STONE = register(new BlockItem("end_stone", builder()));
- public static final Item END_STONE_BRICKS = register(new BlockItem("end_stone_bricks", builder()));
- public static final Item DRAGON_EGG = register(new BlockItem("dragon_egg", builder()));
- public static final Item SANDSTONE_STAIRS = register(new BlockItem("sandstone_stairs", builder()));
- public static final Item ENDER_CHEST = register(new BlockItem("ender_chest", builder()));
- public static final Item EMERALD_BLOCK = register(new BlockItem("emerald_block", builder()));
- public static final Item OAK_STAIRS = register(new BlockItem("oak_stairs", builder()));
- public static final Item SPRUCE_STAIRS = register(new BlockItem("spruce_stairs", builder()));
- public static final Item BIRCH_STAIRS = register(new BlockItem("birch_stairs", builder()));
- public static final Item JUNGLE_STAIRS = register(new BlockItem("jungle_stairs", builder()));
- public static final Item ACACIA_STAIRS = register(new BlockItem("acacia_stairs", builder()));
- public static final Item CHERRY_STAIRS = register(new BlockItem("cherry_stairs", builder()));
- public static final Item DARK_OAK_STAIRS = register(new BlockItem("dark_oak_stairs", builder()));
- public static final Item MANGROVE_STAIRS = register(new BlockItem("mangrove_stairs", builder()));
- public static final Item BAMBOO_STAIRS = register(new BlockItem("bamboo_stairs", builder()));
- public static final Item BAMBOO_MOSAIC_STAIRS = register(new BlockItem("bamboo_mosaic_stairs", builder()));
- public static final Item CRIMSON_STAIRS = register(new BlockItem("crimson_stairs", builder()));
- public static final Item WARPED_STAIRS = register(new BlockItem("warped_stairs", builder()));
- public static final Item COMMAND_BLOCK = register(new BlockItem("command_block", builder()));
- public static final Item BEACON = register(new BlockItem("beacon", builder()));
- public static final Item COBBLESTONE_WALL = register(new BlockItem("cobblestone_wall", builder()));
- public static final Item MOSSY_COBBLESTONE_WALL = register(new BlockItem("mossy_cobblestone_wall", builder()));
- public static final Item BRICK_WALL = register(new BlockItem("brick_wall", builder()));
- public static final Item PRISMARINE_WALL = register(new BlockItem("prismarine_wall", builder()));
- public static final Item RED_SANDSTONE_WALL = register(new BlockItem("red_sandstone_wall", builder()));
- public static final Item MOSSY_STONE_BRICK_WALL = register(new BlockItem("mossy_stone_brick_wall", builder()));
- public static final Item GRANITE_WALL = register(new BlockItem("granite_wall", builder()));
- public static final Item STONE_BRICK_WALL = register(new BlockItem("stone_brick_wall", builder()));
- public static final Item MUD_BRICK_WALL = register(new BlockItem("mud_brick_wall", builder()));
- public static final Item NETHER_BRICK_WALL = register(new BlockItem("nether_brick_wall", builder()));
- public static final Item ANDESITE_WALL = register(new BlockItem("andesite_wall", builder()));
- public static final Item RED_NETHER_BRICK_WALL = register(new BlockItem("red_nether_brick_wall", builder()));
- public static final Item SANDSTONE_WALL = register(new BlockItem("sandstone_wall", builder()));
- public static final Item END_STONE_BRICK_WALL = register(new BlockItem("end_stone_brick_wall", builder()));
- public static final Item DIORITE_WALL = register(new BlockItem("diorite_wall", builder()));
- public static final Item BLACKSTONE_WALL = register(new BlockItem("blackstone_wall", builder()));
- public static final Item POLISHED_BLACKSTONE_WALL = register(new BlockItem("polished_blackstone_wall", builder()));
- public static final Item POLISHED_BLACKSTONE_BRICK_WALL = register(new BlockItem("polished_blackstone_brick_wall", builder()));
- public static final Item COBBLED_DEEPSLATE_WALL = register(new BlockItem("cobbled_deepslate_wall", builder()));
- public static final Item POLISHED_DEEPSLATE_WALL = register(new BlockItem("polished_deepslate_wall", builder()));
- public static final Item DEEPSLATE_BRICK_WALL = register(new BlockItem("deepslate_brick_wall", builder()));
- public static final Item DEEPSLATE_TILE_WALL = register(new BlockItem("deepslate_tile_wall", builder()));
- public static final Item ANVIL = register(new BlockItem("anvil", builder()));
- public static final Item CHIPPED_ANVIL = register(new BlockItem("chipped_anvil", builder()));
- public static final Item DAMAGED_ANVIL = register(new BlockItem("damaged_anvil", builder()));
- public static final Item CHISELED_QUARTZ_BLOCK = register(new BlockItem("chiseled_quartz_block", builder()));
- public static final Item QUARTZ_BLOCK = register(new BlockItem("quartz_block", builder()));
- public static final Item QUARTZ_BRICKS = register(new BlockItem("quartz_bricks", builder()));
- public static final Item QUARTZ_PILLAR = register(new BlockItem("quartz_pillar", builder()));
- public static final Item QUARTZ_STAIRS = register(new BlockItem("quartz_stairs", builder()));
- public static final Item WHITE_TERRACOTTA = register(new BlockItem("white_terracotta", builder()));
- public static final Item ORANGE_TERRACOTTA = register(new BlockItem("orange_terracotta", builder()));
- public static final Item MAGENTA_TERRACOTTA = register(new BlockItem("magenta_terracotta", builder()));
- public static final Item LIGHT_BLUE_TERRACOTTA = register(new BlockItem("light_blue_terracotta", builder()));
- public static final Item YELLOW_TERRACOTTA = register(new BlockItem("yellow_terracotta", builder()));
- public static final Item LIME_TERRACOTTA = register(new BlockItem("lime_terracotta", builder()));
- public static final Item PINK_TERRACOTTA = register(new BlockItem("pink_terracotta", builder()));
- public static final Item GRAY_TERRACOTTA = register(new BlockItem("gray_terracotta", builder()));
- public static final Item LIGHT_GRAY_TERRACOTTA = register(new BlockItem("light_gray_terracotta", builder()));
- public static final Item CYAN_TERRACOTTA = register(new BlockItem("cyan_terracotta", builder()));
- public static final Item PURPLE_TERRACOTTA = register(new BlockItem("purple_terracotta", builder()));
- public static final Item BLUE_TERRACOTTA = register(new BlockItem("blue_terracotta", builder()));
- public static final Item BROWN_TERRACOTTA = register(new BlockItem("brown_terracotta", builder()));
- public static final Item GREEN_TERRACOTTA = register(new BlockItem("green_terracotta", builder()));
- public static final Item RED_TERRACOTTA = register(new BlockItem("red_terracotta", builder()));
- public static final Item BLACK_TERRACOTTA = register(new BlockItem("black_terracotta", builder()));
- public static final Item BARRIER = register(new BlockItem("barrier", builder()));
- public static final Item LIGHT = register(new BlockItem("light", builder()));
- public static final Item HAY_BLOCK = register(new BlockItem("hay_block", builder()));
- public static final Item WHITE_CARPET = register(new BlockItem("white_carpet", builder()));
- public static final Item ORANGE_CARPET = register(new BlockItem("orange_carpet", builder()));
- public static final Item MAGENTA_CARPET = register(new BlockItem("magenta_carpet", builder()));
- public static final Item LIGHT_BLUE_CARPET = register(new BlockItem("light_blue_carpet", builder()));
- public static final Item YELLOW_CARPET = register(new BlockItem("yellow_carpet", builder()));
- public static final Item LIME_CARPET = register(new BlockItem("lime_carpet", builder()));
- public static final Item PINK_CARPET = register(new BlockItem("pink_carpet", builder()));
- public static final Item GRAY_CARPET = register(new BlockItem("gray_carpet", builder()));
- public static final Item LIGHT_GRAY_CARPET = register(new BlockItem("light_gray_carpet", builder()));
- public static final Item CYAN_CARPET = register(new BlockItem("cyan_carpet", builder()));
- public static final Item PURPLE_CARPET = register(new BlockItem("purple_carpet", builder()));
- public static final Item BLUE_CARPET = register(new BlockItem("blue_carpet", builder()));
- public static final Item BROWN_CARPET = register(new BlockItem("brown_carpet", builder()));
- public static final Item GREEN_CARPET = register(new BlockItem("green_carpet", builder()));
- public static final Item RED_CARPET = register(new BlockItem("red_carpet", builder()));
- public static final Item BLACK_CARPET = register(new BlockItem("black_carpet", builder()));
- public static final Item TERRACOTTA = register(new BlockItem("terracotta", builder()));
- public static final Item PACKED_ICE = register(new BlockItem("packed_ice", builder()));
- public static final Item DIRT_PATH = register(new BlockItem("dirt_path", builder()));
- public static final Item SUNFLOWER = register(new BlockItem("sunflower", builder()));
- public static final Item LILAC = register(new BlockItem("lilac", builder()));
- public static final Item ROSE_BUSH = register(new BlockItem("rose_bush", builder()));
- public static final Item PEONY = register(new BlockItem("peony", builder()));
- public static final Item TALL_GRASS = register(new BlockItem("tall_grass", builder()));
- public static final Item LARGE_FERN = register(new BlockItem("large_fern", builder()));
- public static final Item WHITE_STAINED_GLASS = register(new BlockItem("white_stained_glass", builder()));
- public static final Item ORANGE_STAINED_GLASS = register(new BlockItem("orange_stained_glass", builder()));
- public static final Item MAGENTA_STAINED_GLASS = register(new BlockItem("magenta_stained_glass", builder()));
- public static final Item LIGHT_BLUE_STAINED_GLASS = register(new BlockItem("light_blue_stained_glass", builder()));
- public static final Item YELLOW_STAINED_GLASS = register(new BlockItem("yellow_stained_glass", builder()));
- public static final Item LIME_STAINED_GLASS = register(new BlockItem("lime_stained_glass", builder()));
- public static final Item PINK_STAINED_GLASS = register(new BlockItem("pink_stained_glass", builder()));
- public static final Item GRAY_STAINED_GLASS = register(new BlockItem("gray_stained_glass", builder()));
- public static final Item LIGHT_GRAY_STAINED_GLASS = register(new BlockItem("light_gray_stained_glass", builder()));
- public static final Item CYAN_STAINED_GLASS = register(new BlockItem("cyan_stained_glass", builder()));
- public static final Item PURPLE_STAINED_GLASS = register(new BlockItem("purple_stained_glass", builder()));
- public static final Item BLUE_STAINED_GLASS = register(new BlockItem("blue_stained_glass", builder()));
- public static final Item BROWN_STAINED_GLASS = register(new BlockItem("brown_stained_glass", builder()));
- public static final Item GREEN_STAINED_GLASS = register(new BlockItem("green_stained_glass", builder()));
- public static final Item RED_STAINED_GLASS = register(new BlockItem("red_stained_glass", builder()));
- public static final Item BLACK_STAINED_GLASS = register(new BlockItem("black_stained_glass", builder()));
- public static final Item WHITE_STAINED_GLASS_PANE = register(new BlockItem("white_stained_glass_pane", builder()));
- public static final Item ORANGE_STAINED_GLASS_PANE = register(new BlockItem("orange_stained_glass_pane", builder()));
- public static final Item MAGENTA_STAINED_GLASS_PANE = register(new BlockItem("magenta_stained_glass_pane", builder()));
- public static final Item LIGHT_BLUE_STAINED_GLASS_PANE = register(new BlockItem("light_blue_stained_glass_pane", builder()));
- public static final Item YELLOW_STAINED_GLASS_PANE = register(new BlockItem("yellow_stained_glass_pane", builder()));
- public static final Item LIME_STAINED_GLASS_PANE = register(new BlockItem("lime_stained_glass_pane", builder()));
- public static final Item PINK_STAINED_GLASS_PANE = register(new BlockItem("pink_stained_glass_pane", builder()));
- public static final Item GRAY_STAINED_GLASS_PANE = register(new BlockItem("gray_stained_glass_pane", builder()));
- public static final Item LIGHT_GRAY_STAINED_GLASS_PANE = register(new BlockItem("light_gray_stained_glass_pane", builder()));
- public static final Item CYAN_STAINED_GLASS_PANE = register(new BlockItem("cyan_stained_glass_pane", builder()));
- public static final Item PURPLE_STAINED_GLASS_PANE = register(new BlockItem("purple_stained_glass_pane", builder()));
- public static final Item BLUE_STAINED_GLASS_PANE = register(new BlockItem("blue_stained_glass_pane", builder()));
- public static final Item BROWN_STAINED_GLASS_PANE = register(new BlockItem("brown_stained_glass_pane", builder()));
- public static final Item GREEN_STAINED_GLASS_PANE = register(new BlockItem("green_stained_glass_pane", builder()));
- public static final Item RED_STAINED_GLASS_PANE = register(new BlockItem("red_stained_glass_pane", builder()));
- public static final Item BLACK_STAINED_GLASS_PANE = register(new BlockItem("black_stained_glass_pane", builder()));
- public static final Item PRISMARINE = register(new BlockItem("prismarine", builder()));
- public static final Item PRISMARINE_BRICKS = register(new BlockItem("prismarine_bricks", builder()));
- public static final Item DARK_PRISMARINE = register(new BlockItem("dark_prismarine", builder()));
- public static final Item PRISMARINE_STAIRS = register(new BlockItem("prismarine_stairs", builder()));
- public static final Item PRISMARINE_BRICK_STAIRS = register(new BlockItem("prismarine_brick_stairs", builder()));
- public static final Item DARK_PRISMARINE_STAIRS = register(new BlockItem("dark_prismarine_stairs", builder()));
- public static final Item SEA_LANTERN = register(new BlockItem("sea_lantern", builder()));
- public static final Item RED_SANDSTONE = register(new BlockItem("red_sandstone", builder()));
- public static final Item CHISELED_RED_SANDSTONE = register(new BlockItem("chiseled_red_sandstone", builder()));
- public static final Item CUT_RED_SANDSTONE = register(new BlockItem("cut_red_sandstone", builder()));
- public static final Item RED_SANDSTONE_STAIRS = register(new BlockItem("red_sandstone_stairs", builder()));
- public static final Item REPEATING_COMMAND_BLOCK = register(new BlockItem("repeating_command_block", builder()));
- public static final Item CHAIN_COMMAND_BLOCK = register(new BlockItem("chain_command_block", builder()));
- public static final Item MAGMA_BLOCK = register(new BlockItem("magma_block", builder()));
- public static final Item NETHER_WART_BLOCK = register(new BlockItem("nether_wart_block", builder()));
- public static final Item WARPED_WART_BLOCK = register(new BlockItem("warped_wart_block", builder()));
- public static final Item RED_NETHER_BRICKS = register(new BlockItem("red_nether_bricks", builder()));
- public static final Item BONE_BLOCK = register(new BlockItem("bone_block", builder()));
- public static final Item STRUCTURE_VOID = register(new BlockItem("structure_void", builder()));
- public static final Item SHULKER_BOX = register(new ShulkerBoxItem("shulker_box", builder().stackSize(1)));
- public static final Item WHITE_SHULKER_BOX = register(new ShulkerBoxItem("white_shulker_box", builder().stackSize(1)));
- public static final Item ORANGE_SHULKER_BOX = register(new ShulkerBoxItem("orange_shulker_box", builder().stackSize(1)));
- public static final Item MAGENTA_SHULKER_BOX = register(new ShulkerBoxItem("magenta_shulker_box", builder().stackSize(1)));
- public static final Item LIGHT_BLUE_SHULKER_BOX = register(new ShulkerBoxItem("light_blue_shulker_box", builder().stackSize(1)));
- public static final Item YELLOW_SHULKER_BOX = register(new ShulkerBoxItem("yellow_shulker_box", builder().stackSize(1)));
- public static final Item LIME_SHULKER_BOX = register(new ShulkerBoxItem("lime_shulker_box", builder().stackSize(1)));
- public static final Item PINK_SHULKER_BOX = register(new ShulkerBoxItem("pink_shulker_box", builder().stackSize(1)));
- public static final Item GRAY_SHULKER_BOX = register(new ShulkerBoxItem("gray_shulker_box", builder().stackSize(1)));
- public static final Item LIGHT_GRAY_SHULKER_BOX = register(new ShulkerBoxItem("light_gray_shulker_box", builder().stackSize(1)));
- public static final Item CYAN_SHULKER_BOX = register(new ShulkerBoxItem("cyan_shulker_box", builder().stackSize(1)));
- public static final Item PURPLE_SHULKER_BOX = register(new ShulkerBoxItem("purple_shulker_box", builder().stackSize(1)));
- public static final Item BLUE_SHULKER_BOX = register(new ShulkerBoxItem("blue_shulker_box", builder().stackSize(1)));
- public static final Item BROWN_SHULKER_BOX = register(new ShulkerBoxItem("brown_shulker_box", builder().stackSize(1)));
- public static final Item GREEN_SHULKER_BOX = register(new ShulkerBoxItem("green_shulker_box", builder().stackSize(1)));
- public static final Item RED_SHULKER_BOX = register(new ShulkerBoxItem("red_shulker_box", builder().stackSize(1)));
- public static final Item BLACK_SHULKER_BOX = register(new ShulkerBoxItem("black_shulker_box", builder().stackSize(1)));
- public static final Item WHITE_GLAZED_TERRACOTTA = register(new BlockItem("white_glazed_terracotta", builder()));
- public static final Item ORANGE_GLAZED_TERRACOTTA = register(new BlockItem("orange_glazed_terracotta", builder()));
- public static final Item MAGENTA_GLAZED_TERRACOTTA = register(new BlockItem("magenta_glazed_terracotta", builder()));
- public static final Item LIGHT_BLUE_GLAZED_TERRACOTTA = register(new BlockItem("light_blue_glazed_terracotta", builder()));
- public static final Item YELLOW_GLAZED_TERRACOTTA = register(new BlockItem("yellow_glazed_terracotta", builder()));
- public static final Item LIME_GLAZED_TERRACOTTA = register(new BlockItem("lime_glazed_terracotta", builder()));
- public static final Item PINK_GLAZED_TERRACOTTA = register(new BlockItem("pink_glazed_terracotta", builder()));
- public static final Item GRAY_GLAZED_TERRACOTTA = register(new BlockItem("gray_glazed_terracotta", builder()));
- public static final Item LIGHT_GRAY_GLAZED_TERRACOTTA = register(new BlockItem("light_gray_glazed_terracotta", builder()));
- public static final Item CYAN_GLAZED_TERRACOTTA = register(new BlockItem("cyan_glazed_terracotta", builder()));
- public static final Item PURPLE_GLAZED_TERRACOTTA = register(new BlockItem("purple_glazed_terracotta", builder()));
- public static final Item BLUE_GLAZED_TERRACOTTA = register(new BlockItem("blue_glazed_terracotta", builder()));
- public static final Item BROWN_GLAZED_TERRACOTTA = register(new BlockItem("brown_glazed_terracotta", builder()));
- public static final Item GREEN_GLAZED_TERRACOTTA = register(new BlockItem("green_glazed_terracotta", builder()));
- public static final Item RED_GLAZED_TERRACOTTA = register(new BlockItem("red_glazed_terracotta", builder()));
- public static final Item BLACK_GLAZED_TERRACOTTA = register(new BlockItem("black_glazed_terracotta", builder()));
- public static final Item WHITE_CONCRETE = register(new BlockItem("white_concrete", builder()));
- public static final Item ORANGE_CONCRETE = register(new BlockItem("orange_concrete", builder()));
- public static final Item MAGENTA_CONCRETE = register(new BlockItem("magenta_concrete", builder()));
- public static final Item LIGHT_BLUE_CONCRETE = register(new BlockItem("light_blue_concrete", builder()));
- public static final Item YELLOW_CONCRETE = register(new BlockItem("yellow_concrete", builder()));
- public static final Item LIME_CONCRETE = register(new BlockItem("lime_concrete", builder()));
- public static final Item PINK_CONCRETE = register(new BlockItem("pink_concrete", builder()));
- public static final Item GRAY_CONCRETE = register(new BlockItem("gray_concrete", builder()));
- public static final Item LIGHT_GRAY_CONCRETE = register(new BlockItem("light_gray_concrete", builder()));
- public static final Item CYAN_CONCRETE = register(new BlockItem("cyan_concrete", builder()));
- public static final Item PURPLE_CONCRETE = register(new BlockItem("purple_concrete", builder()));
- public static final Item BLUE_CONCRETE = register(new BlockItem("blue_concrete", builder()));
- public static final Item BROWN_CONCRETE = register(new BlockItem("brown_concrete", builder()));
- public static final Item GREEN_CONCRETE = register(new BlockItem("green_concrete", builder()));
- public static final Item RED_CONCRETE = register(new BlockItem("red_concrete", builder()));
- public static final Item BLACK_CONCRETE = register(new BlockItem("black_concrete", builder()));
- public static final Item WHITE_CONCRETE_POWDER = register(new BlockItem("white_concrete_powder", builder()));
- public static final Item ORANGE_CONCRETE_POWDER = register(new BlockItem("orange_concrete_powder", builder()));
- public static final Item MAGENTA_CONCRETE_POWDER = register(new BlockItem("magenta_concrete_powder", builder()));
- public static final Item LIGHT_BLUE_CONCRETE_POWDER = register(new BlockItem("light_blue_concrete_powder", builder()));
- public static final Item YELLOW_CONCRETE_POWDER = register(new BlockItem("yellow_concrete_powder", builder()));
- public static final Item LIME_CONCRETE_POWDER = register(new BlockItem("lime_concrete_powder", builder()));
- public static final Item PINK_CONCRETE_POWDER = register(new BlockItem("pink_concrete_powder", builder()));
- public static final Item GRAY_CONCRETE_POWDER = register(new BlockItem("gray_concrete_powder", builder()));
- public static final Item LIGHT_GRAY_CONCRETE_POWDER = register(new BlockItem("light_gray_concrete_powder", builder()));
- public static final Item CYAN_CONCRETE_POWDER = register(new BlockItem("cyan_concrete_powder", builder()));
- public static final Item PURPLE_CONCRETE_POWDER = register(new BlockItem("purple_concrete_powder", builder()));
- public static final Item BLUE_CONCRETE_POWDER = register(new BlockItem("blue_concrete_powder", builder()));
- public static final Item BROWN_CONCRETE_POWDER = register(new BlockItem("brown_concrete_powder", builder()));
- public static final Item GREEN_CONCRETE_POWDER = register(new BlockItem("green_concrete_powder", builder()));
- public static final Item RED_CONCRETE_POWDER = register(new BlockItem("red_concrete_powder", builder()));
- public static final Item BLACK_CONCRETE_POWDER = register(new BlockItem("black_concrete_powder", builder()));
- public static final Item TURTLE_EGG = register(new BlockItem("turtle_egg", builder()));
- public static final Item SNIFFER_EGG = register(new BlockItem("sniffer_egg", builder()));
- public static final Item DEAD_TUBE_CORAL_BLOCK = register(new BlockItem("dead_tube_coral_block", builder()));
- public static final Item DEAD_BRAIN_CORAL_BLOCK = register(new BlockItem("dead_brain_coral_block", builder()));
- public static final Item DEAD_BUBBLE_CORAL_BLOCK = register(new BlockItem("dead_bubble_coral_block", builder()));
- public static final Item DEAD_FIRE_CORAL_BLOCK = register(new BlockItem("dead_fire_coral_block", builder()));
- public static final Item DEAD_HORN_CORAL_BLOCK = register(new BlockItem("dead_horn_coral_block", builder()));
- public static final Item TUBE_CORAL_BLOCK = register(new BlockItem("tube_coral_block", builder()));
- public static final Item BRAIN_CORAL_BLOCK = register(new BlockItem("brain_coral_block", builder()));
- public static final Item BUBBLE_CORAL_BLOCK = register(new BlockItem("bubble_coral_block", builder()));
- public static final Item FIRE_CORAL_BLOCK = register(new BlockItem("fire_coral_block", builder()));
- public static final Item HORN_CORAL_BLOCK = register(new BlockItem("horn_coral_block", builder()));
- public static final Item TUBE_CORAL = register(new BlockItem("tube_coral", builder()));
- public static final Item BRAIN_CORAL = register(new BlockItem("brain_coral", builder()));
- public static final Item BUBBLE_CORAL = register(new BlockItem("bubble_coral", builder()));
- public static final Item FIRE_CORAL = register(new BlockItem("fire_coral", builder()));
- public static final Item HORN_CORAL = register(new BlockItem("horn_coral", builder()));
- public static final Item DEAD_BRAIN_CORAL = register(new BlockItem("dead_brain_coral", builder()));
- public static final Item DEAD_BUBBLE_CORAL = register(new BlockItem("dead_bubble_coral", builder()));
- public static final Item DEAD_FIRE_CORAL = register(new BlockItem("dead_fire_coral", builder()));
- public static final Item DEAD_HORN_CORAL = register(new BlockItem("dead_horn_coral", builder()));
- public static final Item DEAD_TUBE_CORAL = register(new BlockItem("dead_tube_coral", builder()));
- public static final Item TUBE_CORAL_FAN = register(new BlockItem("tube_coral_fan", builder()));
- public static final Item BRAIN_CORAL_FAN = register(new BlockItem("brain_coral_fan", builder()));
- public static final Item BUBBLE_CORAL_FAN = register(new BlockItem("bubble_coral_fan", builder()));
- public static final Item FIRE_CORAL_FAN = register(new BlockItem("fire_coral_fan", builder()));
- public static final Item HORN_CORAL_FAN = register(new BlockItem("horn_coral_fan", builder()));
- public static final Item DEAD_TUBE_CORAL_FAN = register(new BlockItem("dead_tube_coral_fan", builder()));
- public static final Item DEAD_BRAIN_CORAL_FAN = register(new BlockItem("dead_brain_coral_fan", builder()));
- public static final Item DEAD_BUBBLE_CORAL_FAN = register(new BlockItem("dead_bubble_coral_fan", builder()));
- public static final Item DEAD_FIRE_CORAL_FAN = register(new BlockItem("dead_fire_coral_fan", builder()));
- public static final Item DEAD_HORN_CORAL_FAN = register(new BlockItem("dead_horn_coral_fan", builder()));
- public static final Item BLUE_ICE = register(new BlockItem("blue_ice", builder()));
- public static final Item CONDUIT = register(new BlockItem("conduit", builder()));
- public static final Item POLISHED_GRANITE_STAIRS = register(new BlockItem("polished_granite_stairs", builder()));
- public static final Item SMOOTH_RED_SANDSTONE_STAIRS = register(new BlockItem("smooth_red_sandstone_stairs", builder()));
- public static final Item MOSSY_STONE_BRICK_STAIRS = register(new BlockItem("mossy_stone_brick_stairs", builder()));
- public static final Item POLISHED_DIORITE_STAIRS = register(new BlockItem("polished_diorite_stairs", builder()));
- public static final Item MOSSY_COBBLESTONE_STAIRS = register(new BlockItem("mossy_cobblestone_stairs", builder()));
- public static final Item END_STONE_BRICK_STAIRS = register(new BlockItem("end_stone_brick_stairs", builder()));
- public static final Item STONE_STAIRS = register(new BlockItem("stone_stairs", builder()));
- public static final Item SMOOTH_SANDSTONE_STAIRS = register(new BlockItem("smooth_sandstone_stairs", builder()));
- public static final Item SMOOTH_QUARTZ_STAIRS = register(new BlockItem("smooth_quartz_stairs", builder()));
- public static final Item GRANITE_STAIRS = register(new BlockItem("granite_stairs", builder()));
- public static final Item ANDESITE_STAIRS = register(new BlockItem("andesite_stairs", builder()));
- public static final Item RED_NETHER_BRICK_STAIRS = register(new BlockItem("red_nether_brick_stairs", builder()));
- public static final Item POLISHED_ANDESITE_STAIRS = register(new BlockItem("polished_andesite_stairs", builder()));
- public static final Item DIORITE_STAIRS = register(new BlockItem("diorite_stairs", builder()));
- public static final Item COBBLED_DEEPSLATE_STAIRS = register(new BlockItem("cobbled_deepslate_stairs", builder()));
- public static final Item POLISHED_DEEPSLATE_STAIRS = register(new BlockItem("polished_deepslate_stairs", builder()));
- public static final Item DEEPSLATE_BRICK_STAIRS = register(new BlockItem("deepslate_brick_stairs", builder()));
- public static final Item DEEPSLATE_TILE_STAIRS = register(new BlockItem("deepslate_tile_stairs", builder()));
- public static final Item POLISHED_GRANITE_SLAB = register(new BlockItem("polished_granite_slab", builder()));
- public static final Item SMOOTH_RED_SANDSTONE_SLAB = register(new BlockItem("smooth_red_sandstone_slab", builder()));
- public static final Item MOSSY_STONE_BRICK_SLAB = register(new BlockItem("mossy_stone_brick_slab", builder()));
- public static final Item POLISHED_DIORITE_SLAB = register(new BlockItem("polished_diorite_slab", builder()));
- public static final Item MOSSY_COBBLESTONE_SLAB = register(new BlockItem("mossy_cobblestone_slab", builder()));
- public static final Item END_STONE_BRICK_SLAB = register(new BlockItem("end_stone_brick_slab", builder()));
- public static final Item SMOOTH_SANDSTONE_SLAB = register(new BlockItem("smooth_sandstone_slab", builder()));
- public static final Item SMOOTH_QUARTZ_SLAB = register(new BlockItem("smooth_quartz_slab", builder()));
- public static final Item GRANITE_SLAB = register(new BlockItem("granite_slab", builder()));
- public static final Item ANDESITE_SLAB = register(new BlockItem("andesite_slab", builder()));
- public static final Item RED_NETHER_BRICK_SLAB = register(new BlockItem("red_nether_brick_slab", builder()));
- public static final Item POLISHED_ANDESITE_SLAB = register(new BlockItem("polished_andesite_slab", builder()));
- public static final Item DIORITE_SLAB = register(new BlockItem("diorite_slab", builder()));
- public static final Item COBBLED_DEEPSLATE_SLAB = register(new BlockItem("cobbled_deepslate_slab", builder()));
- public static final Item POLISHED_DEEPSLATE_SLAB = register(new BlockItem("polished_deepslate_slab", builder()));
- public static final Item DEEPSLATE_BRICK_SLAB = register(new BlockItem("deepslate_brick_slab", builder()));
- public static final Item DEEPSLATE_TILE_SLAB = register(new BlockItem("deepslate_tile_slab", builder()));
- public static final Item SCAFFOLDING = register(new BlockItem("scaffolding", builder()));
- public static final Item REDSTONE = register(new BlockItem("redstone", builder()));
- public static final Item REDSTONE_TORCH = register(new BlockItem("redstone_torch", builder()));
- public static final Item REDSTONE_BLOCK = register(new BlockItem("redstone_block", builder()));
- public static final Item REPEATER = register(new BlockItem("repeater", builder()));
- public static final Item COMPARATOR = register(new BlockItem("comparator", builder()));
- public static final Item PISTON = register(new BlockItem("piston", builder()));
- public static final Item STICKY_PISTON = register(new BlockItem("sticky_piston", builder()));
- public static final Item SLIME_BLOCK = register(new BlockItem("slime_block", builder()));
- public static final Item HONEY_BLOCK = register(new BlockItem("honey_block", builder()));
- public static final Item OBSERVER = register(new BlockItem("observer", builder()));
- public static final Item HOPPER = register(new BlockItem("hopper", builder()));
- public static final Item DISPENSER = register(new BlockItem("dispenser", builder()));
- public static final Item DROPPER = register(new BlockItem("dropper", builder()));
- public static final Item LECTERN = register(new BlockItem("lectern", builder()));
- public static final Item TARGET = register(new BlockItem("target", builder()));
- public static final Item LEVER = register(new BlockItem("lever", builder()));
- public static final Item LIGHTNING_ROD = register(new BlockItem("lightning_rod", builder()));
- public static final Item DAYLIGHT_DETECTOR = register(new BlockItem("daylight_detector", builder()));
- public static final Item SCULK_SENSOR = register(new BlockItem("sculk_sensor", builder()));
- public static final Item CALIBRATED_SCULK_SENSOR = register(new BlockItem("calibrated_sculk_sensor", builder()));
- public static final Item TRIPWIRE_HOOK = register(new BlockItem("tripwire_hook", builder()));
- public static final Item TRAPPED_CHEST = register(new BlockItem("trapped_chest", builder()));
- public static final Item TNT = register(new BlockItem("tnt", builder()));
- public static final Item REDSTONE_LAMP = register(new BlockItem("redstone_lamp", builder()));
- public static final Item NOTE_BLOCK = register(new BlockItem("note_block", builder()));
- public static final Item STONE_BUTTON = register(new BlockItem("stone_button", builder()));
- public static final Item POLISHED_BLACKSTONE_BUTTON = register(new BlockItem("polished_blackstone_button", builder()));
- public static final Item OAK_BUTTON = register(new BlockItem("oak_button", builder()));
- public static final Item SPRUCE_BUTTON = register(new BlockItem("spruce_button", builder()));
- public static final Item BIRCH_BUTTON = register(new BlockItem("birch_button", builder()));
- public static final Item JUNGLE_BUTTON = register(new BlockItem("jungle_button", builder()));
- public static final Item ACACIA_BUTTON = register(new BlockItem("acacia_button", builder()));
- public static final Item CHERRY_BUTTON = register(new BlockItem("cherry_button", builder()));
- public static final Item DARK_OAK_BUTTON = register(new BlockItem("dark_oak_button", builder()));
- public static final Item MANGROVE_BUTTON = register(new BlockItem("mangrove_button", builder()));
- public static final Item BAMBOO_BUTTON = register(new BlockItem("bamboo_button", builder()));
- public static final Item CRIMSON_BUTTON = register(new BlockItem("crimson_button", builder()));
- public static final Item WARPED_BUTTON = register(new BlockItem("warped_button", builder()));
- public static final Item STONE_PRESSURE_PLATE = register(new BlockItem("stone_pressure_plate", builder()));
- public static final Item POLISHED_BLACKSTONE_PRESSURE_PLATE = register(new BlockItem("polished_blackstone_pressure_plate", builder()));
- public static final Item LIGHT_WEIGHTED_PRESSURE_PLATE = register(new BlockItem("light_weighted_pressure_plate", builder()));
- public static final Item HEAVY_WEIGHTED_PRESSURE_PLATE = register(new BlockItem("heavy_weighted_pressure_plate", builder()));
- public static final Item OAK_PRESSURE_PLATE = register(new BlockItem("oak_pressure_plate", builder()));
- public static final Item SPRUCE_PRESSURE_PLATE = register(new BlockItem("spruce_pressure_plate", builder()));
- public static final Item BIRCH_PRESSURE_PLATE = register(new BlockItem("birch_pressure_plate", builder()));
- public static final Item JUNGLE_PRESSURE_PLATE = register(new BlockItem("jungle_pressure_plate", builder()));
- public static final Item ACACIA_PRESSURE_PLATE = register(new BlockItem("acacia_pressure_plate", builder()));
- public static final Item CHERRY_PRESSURE_PLATE = register(new BlockItem("cherry_pressure_plate", builder()));
- public static final Item DARK_OAK_PRESSURE_PLATE = register(new BlockItem("dark_oak_pressure_plate", builder()));
- public static final Item MANGROVE_PRESSURE_PLATE = register(new BlockItem("mangrove_pressure_plate", builder()));
- public static final Item BAMBOO_PRESSURE_PLATE = register(new BlockItem("bamboo_pressure_plate", builder()));
- public static final Item CRIMSON_PRESSURE_PLATE = register(new BlockItem("crimson_pressure_plate", builder()));
- public static final Item WARPED_PRESSURE_PLATE = register(new BlockItem("warped_pressure_plate", builder()));
- public static final Item IRON_DOOR = register(new BlockItem("iron_door", builder()));
- public static final Item OAK_DOOR = register(new BlockItem("oak_door", builder()));
- public static final Item SPRUCE_DOOR = register(new BlockItem("spruce_door", builder()));
- public static final Item BIRCH_DOOR = register(new BlockItem("birch_door", builder()));
- public static final Item JUNGLE_DOOR = register(new BlockItem("jungle_door", builder()));
- public static final Item ACACIA_DOOR = register(new BlockItem("acacia_door", builder()));
- public static final Item CHERRY_DOOR = register(new BlockItem("cherry_door", builder()));
- public static final Item DARK_OAK_DOOR = register(new BlockItem("dark_oak_door", builder()));
- public static final Item MANGROVE_DOOR = register(new BlockItem("mangrove_door", builder()));
- public static final Item BAMBOO_DOOR = register(new BlockItem("bamboo_door", builder()));
- public static final Item CRIMSON_DOOR = register(new BlockItem("crimson_door", builder()));
- public static final Item WARPED_DOOR = register(new BlockItem("warped_door", builder()));
- public static final Item COPPER_DOOR = register(new BlockItem("copper_door", builder()));
- public static final Item EXPOSED_COPPER_DOOR = register(new BlockItem("exposed_copper_door", builder()));
- public static final Item WEATHERED_COPPER_DOOR = register(new BlockItem("weathered_copper_door", builder()));
- public static final Item OXIDIZED_COPPER_DOOR = register(new BlockItem("oxidized_copper_door", builder()));
- public static final Item WAXED_COPPER_DOOR = register(new BlockItem("waxed_copper_door", builder()));
- public static final Item WAXED_EXPOSED_COPPER_DOOR = register(new BlockItem("waxed_exposed_copper_door", builder()));
- public static final Item WAXED_WEATHERED_COPPER_DOOR = register(new BlockItem("waxed_weathered_copper_door", builder()));
- public static final Item WAXED_OXIDIZED_COPPER_DOOR = register(new BlockItem("waxed_oxidized_copper_door", builder()));
- public static final Item IRON_TRAPDOOR = register(new BlockItem("iron_trapdoor", builder()));
- public static final Item OAK_TRAPDOOR = register(new BlockItem("oak_trapdoor", builder()));
- public static final Item SPRUCE_TRAPDOOR = register(new BlockItem("spruce_trapdoor", builder()));
- public static final Item BIRCH_TRAPDOOR = register(new BlockItem("birch_trapdoor", builder()));
- public static final Item JUNGLE_TRAPDOOR = register(new BlockItem("jungle_trapdoor", builder()));
- public static final Item ACACIA_TRAPDOOR = register(new BlockItem("acacia_trapdoor", builder()));
- public static final Item CHERRY_TRAPDOOR = register(new BlockItem("cherry_trapdoor", builder()));
- public static final Item DARK_OAK_TRAPDOOR = register(new BlockItem("dark_oak_trapdoor", builder()));
- public static final Item MANGROVE_TRAPDOOR = register(new BlockItem("mangrove_trapdoor", builder()));
- public static final Item BAMBOO_TRAPDOOR = register(new BlockItem("bamboo_trapdoor", builder()));
- public static final Item CRIMSON_TRAPDOOR = register(new BlockItem("crimson_trapdoor", builder()));
- public static final Item WARPED_TRAPDOOR = register(new BlockItem("warped_trapdoor", builder()));
- public static final Item COPPER_TRAPDOOR = register(new BlockItem("copper_trapdoor", builder()));
- public static final Item EXPOSED_COPPER_TRAPDOOR = register(new BlockItem("exposed_copper_trapdoor", builder()));
- public static final Item WEATHERED_COPPER_TRAPDOOR = register(new BlockItem("weathered_copper_trapdoor", builder()));
- public static final Item OXIDIZED_COPPER_TRAPDOOR = register(new BlockItem("oxidized_copper_trapdoor", builder()));
- public static final Item WAXED_COPPER_TRAPDOOR = register(new BlockItem("waxed_copper_trapdoor", builder()));
- public static final Item WAXED_EXPOSED_COPPER_TRAPDOOR = register(new BlockItem("waxed_exposed_copper_trapdoor", builder()));
- public static final Item WAXED_WEATHERED_COPPER_TRAPDOOR = register(new BlockItem("waxed_weathered_copper_trapdoor", builder()));
- public static final Item WAXED_OXIDIZED_COPPER_TRAPDOOR = register(new BlockItem("waxed_oxidized_copper_trapdoor", builder()));
- public static final Item OAK_FENCE_GATE = register(new BlockItem("oak_fence_gate", builder()));
- public static final Item SPRUCE_FENCE_GATE = register(new BlockItem("spruce_fence_gate", builder()));
- public static final Item BIRCH_FENCE_GATE = register(new BlockItem("birch_fence_gate", builder()));
- public static final Item JUNGLE_FENCE_GATE = register(new BlockItem("jungle_fence_gate", builder()));
- public static final Item ACACIA_FENCE_GATE = register(new BlockItem("acacia_fence_gate", builder()));
- public static final Item CHERRY_FENCE_GATE = register(new BlockItem("cherry_fence_gate", builder()));
- public static final Item DARK_OAK_FENCE_GATE = register(new BlockItem("dark_oak_fence_gate", builder()));
- public static final Item MANGROVE_FENCE_GATE = register(new BlockItem("mangrove_fence_gate", builder()));
- public static final Item BAMBOO_FENCE_GATE = register(new BlockItem("bamboo_fence_gate", builder()));
- public static final Item CRIMSON_FENCE_GATE = register(new BlockItem("crimson_fence_gate", builder()));
- public static final Item WARPED_FENCE_GATE = register(new BlockItem("warped_fence_gate", builder()));
- public static final Item POWERED_RAIL = register(new BlockItem("powered_rail", builder()));
- public static final Item DETECTOR_RAIL = register(new BlockItem("detector_rail", builder()));
- public static final Item RAIL = register(new BlockItem("rail", builder()));
- public static final Item ACTIVATOR_RAIL = register(new BlockItem("activator_rail", builder()));
+ public static final Item STONE = register(new BlockItem(builder(), Blocks.STONE));
+ public static final Item GRANITE = register(new BlockItem(builder(), Blocks.GRANITE));
+ public static final Item POLISHED_GRANITE = register(new BlockItem(builder(), Blocks.POLISHED_GRANITE));
+ public static final Item DIORITE = register(new BlockItem(builder(), Blocks.DIORITE));
+ public static final Item POLISHED_DIORITE = register(new BlockItem(builder(), Blocks.POLISHED_DIORITE));
+ public static final Item ANDESITE = register(new BlockItem(builder(), Blocks.ANDESITE));
+ public static final Item POLISHED_ANDESITE = register(new BlockItem(builder(), Blocks.POLISHED_ANDESITE));
+ public static final Item DEEPSLATE = register(new BlockItem(builder(), Blocks.DEEPSLATE));
+ public static final Item COBBLED_DEEPSLATE = register(new BlockItem(builder(), Blocks.COBBLED_DEEPSLATE));
+ public static final Item POLISHED_DEEPSLATE = register(new BlockItem(builder(), Blocks.POLISHED_DEEPSLATE));
+ public static final Item CALCITE = register(new BlockItem(builder(), Blocks.CALCITE));
+ public static final Item TUFF = register(new BlockItem(builder(), Blocks.TUFF));
+ public static final Item TUFF_SLAB = register(new BlockItem(builder(), Blocks.TUFF_SLAB));
+ public static final Item TUFF_STAIRS = register(new BlockItem(builder(), Blocks.TUFF_STAIRS));
+ public static final Item TUFF_WALL = register(new BlockItem(builder(), Blocks.TUFF_WALL));
+ public static final Item CHISELED_TUFF = register(new BlockItem(builder(), Blocks.CHISELED_TUFF));
+ public static final Item POLISHED_TUFF = register(new BlockItem(builder(), Blocks.POLISHED_TUFF));
+ public static final Item POLISHED_TUFF_SLAB = register(new BlockItem(builder(), Blocks.POLISHED_TUFF_SLAB));
+ public static final Item POLISHED_TUFF_STAIRS = register(new BlockItem(builder(), Blocks.POLISHED_TUFF_STAIRS));
+ public static final Item POLISHED_TUFF_WALL = register(new BlockItem(builder(), Blocks.POLISHED_TUFF_WALL));
+ public static final Item TUFF_BRICKS = register(new BlockItem(builder(), Blocks.TUFF_BRICKS));
+ public static final Item TUFF_BRICK_SLAB = register(new BlockItem(builder(), Blocks.TUFF_BRICK_SLAB));
+ public static final Item TUFF_BRICK_STAIRS = register(new BlockItem(builder(), Blocks.TUFF_BRICK_STAIRS));
+ public static final Item TUFF_BRICK_WALL = register(new BlockItem(builder(), Blocks.TUFF_BRICK_WALL));
+ public static final Item CHISELED_TUFF_BRICKS = register(new BlockItem(builder(), Blocks.CHISELED_TUFF_BRICKS));
+ public static final Item DRIPSTONE_BLOCK = register(new BlockItem(builder(), Blocks.DRIPSTONE_BLOCK));
+ public static final Item GRASS_BLOCK = register(new BlockItem(builder(), Blocks.GRASS_BLOCK));
+ public static final Item DIRT = register(new BlockItem(builder(), Blocks.DIRT));
+ public static final Item COARSE_DIRT = register(new BlockItem(builder(), Blocks.COARSE_DIRT));
+ public static final Item PODZOL = register(new BlockItem(builder(), Blocks.PODZOL));
+ public static final Item ROOTED_DIRT = register(new BlockItem(builder(), Blocks.ROOTED_DIRT));
+ public static final Item MUD = register(new BlockItem(builder(), Blocks.MUD));
+ public static final Item CRIMSON_NYLIUM = register(new BlockItem(builder(), Blocks.CRIMSON_NYLIUM));
+ public static final Item WARPED_NYLIUM = register(new BlockItem(builder(), Blocks.WARPED_NYLIUM));
+ public static final Item COBBLESTONE = register(new BlockItem(builder(), Blocks.COBBLESTONE));
+ public static final Item OAK_PLANKS = register(new BlockItem(builder(), Blocks.OAK_PLANKS));
+ public static final Item SPRUCE_PLANKS = register(new BlockItem(builder(), Blocks.SPRUCE_PLANKS));
+ public static final Item BIRCH_PLANKS = register(new BlockItem(builder(), Blocks.BIRCH_PLANKS));
+ public static final Item JUNGLE_PLANKS = register(new BlockItem(builder(), Blocks.JUNGLE_PLANKS));
+ public static final Item ACACIA_PLANKS = register(new BlockItem(builder(), Blocks.ACACIA_PLANKS));
+ public static final Item CHERRY_PLANKS = register(new BlockItem(builder(), Blocks.CHERRY_PLANKS));
+ public static final Item DARK_OAK_PLANKS = register(new BlockItem(builder(), Blocks.DARK_OAK_PLANKS));
+ public static final Item MANGROVE_PLANKS = register(new BlockItem(builder(), Blocks.MANGROVE_PLANKS));
+ public static final Item BAMBOO_PLANKS = register(new BlockItem(builder(), Blocks.BAMBOO_PLANKS));
+ public static final Item CRIMSON_PLANKS = register(new BlockItem(builder(), Blocks.CRIMSON_PLANKS));
+ public static final Item WARPED_PLANKS = register(new BlockItem(builder(), Blocks.WARPED_PLANKS));
+ public static final Item BAMBOO_MOSAIC = register(new BlockItem(builder(), Blocks.BAMBOO_MOSAIC));
+ public static final Item OAK_SAPLING = register(new BlockItem(builder(), Blocks.OAK_SAPLING));
+ public static final Item SPRUCE_SAPLING = register(new BlockItem(builder(), Blocks.SPRUCE_SAPLING));
+ public static final Item BIRCH_SAPLING = register(new BlockItem(builder(), Blocks.BIRCH_SAPLING));
+ public static final Item JUNGLE_SAPLING = register(new BlockItem(builder(), Blocks.JUNGLE_SAPLING));
+ public static final Item ACACIA_SAPLING = register(new BlockItem(builder(), Blocks.ACACIA_SAPLING));
+ public static final Item CHERRY_SAPLING = register(new BlockItem(builder(), Blocks.CHERRY_SAPLING));
+ public static final Item DARK_OAK_SAPLING = register(new BlockItem(builder(), Blocks.DARK_OAK_SAPLING));
+ public static final Item MANGROVE_PROPAGULE = register(new BlockItem(builder(), Blocks.MANGROVE_PROPAGULE));
+ public static final Item BEDROCK = register(new BlockItem(builder(), Blocks.BEDROCK));
+ public static final Item SAND = register(new BlockItem(builder(), Blocks.SAND));
+ public static final Item SUSPICIOUS_SAND = register(new BlockItem(builder(), Blocks.SUSPICIOUS_SAND));
+ public static final Item SUSPICIOUS_GRAVEL = register(new BlockItem(builder(), Blocks.SUSPICIOUS_GRAVEL));
+ public static final Item RED_SAND = register(new BlockItem(builder(), Blocks.RED_SAND));
+ public static final Item GRAVEL = register(new BlockItem(builder(), Blocks.GRAVEL));
+ public static final Item COAL_ORE = register(new BlockItem(builder(), Blocks.COAL_ORE));
+ public static final Item DEEPSLATE_COAL_ORE = register(new BlockItem(builder(), Blocks.DEEPSLATE_COAL_ORE));
+ public static final Item IRON_ORE = register(new BlockItem(builder(), Blocks.IRON_ORE));
+ public static final Item DEEPSLATE_IRON_ORE = register(new BlockItem(builder(), Blocks.DEEPSLATE_IRON_ORE));
+ public static final Item COPPER_ORE = register(new BlockItem(builder(), Blocks.COPPER_ORE));
+ public static final Item DEEPSLATE_COPPER_ORE = register(new BlockItem(builder(), Blocks.DEEPSLATE_COPPER_ORE));
+ public static final Item GOLD_ORE = register(new BlockItem(builder(), Blocks.GOLD_ORE));
+ public static final Item DEEPSLATE_GOLD_ORE = register(new BlockItem(builder(), Blocks.DEEPSLATE_GOLD_ORE));
+ public static final Item REDSTONE_ORE = register(new BlockItem(builder(), Blocks.REDSTONE_ORE));
+ public static final Item DEEPSLATE_REDSTONE_ORE = register(new BlockItem(builder(), Blocks.DEEPSLATE_REDSTONE_ORE));
+ public static final Item EMERALD_ORE = register(new BlockItem(builder(), Blocks.EMERALD_ORE));
+ public static final Item DEEPSLATE_EMERALD_ORE = register(new BlockItem(builder(), Blocks.DEEPSLATE_EMERALD_ORE));
+ public static final Item LAPIS_ORE = register(new BlockItem(builder(), Blocks.LAPIS_ORE));
+ public static final Item DEEPSLATE_LAPIS_ORE = register(new BlockItem(builder(), Blocks.DEEPSLATE_LAPIS_ORE));
+ public static final Item DIAMOND_ORE = register(new BlockItem(builder(), Blocks.DIAMOND_ORE));
+ public static final Item DEEPSLATE_DIAMOND_ORE = register(new BlockItem(builder(), Blocks.DEEPSLATE_DIAMOND_ORE));
+ public static final Item NETHER_GOLD_ORE = register(new BlockItem(builder(), Blocks.NETHER_GOLD_ORE));
+ public static final Item NETHER_QUARTZ_ORE = register(new BlockItem(builder(), Blocks.NETHER_QUARTZ_ORE));
+ public static final Item ANCIENT_DEBRIS = register(new BlockItem(builder(), Blocks.ANCIENT_DEBRIS));
+ public static final Item COAL_BLOCK = register(new BlockItem(builder(), Blocks.COAL_BLOCK));
+ public static final Item RAW_IRON_BLOCK = register(new BlockItem(builder(), Blocks.RAW_IRON_BLOCK));
+ public static final Item RAW_COPPER_BLOCK = register(new BlockItem(builder(), Blocks.RAW_COPPER_BLOCK));
+ public static final Item RAW_GOLD_BLOCK = register(new BlockItem(builder(), Blocks.RAW_GOLD_BLOCK));
+ public static final Item HEAVY_CORE = register(new BlockItem(builder(), Blocks.HEAVY_CORE));
+ public static final Item AMETHYST_BLOCK = register(new BlockItem(builder(), Blocks.AMETHYST_BLOCK));
+ public static final Item BUDDING_AMETHYST = register(new BlockItem(builder(), Blocks.BUDDING_AMETHYST));
+ public static final Item IRON_BLOCK = register(new BlockItem(builder(), Blocks.IRON_BLOCK));
+ public static final Item COPPER_BLOCK = register(new BlockItem(builder(), Blocks.COPPER_BLOCK));
+ public static final Item GOLD_BLOCK = register(new BlockItem(builder(), Blocks.GOLD_BLOCK));
+ public static final Item DIAMOND_BLOCK = register(new BlockItem(builder(), Blocks.DIAMOND_BLOCK));
+ public static final Item NETHERITE_BLOCK = register(new BlockItem(builder(), Blocks.NETHERITE_BLOCK));
+ public static final Item EXPOSED_COPPER = register(new BlockItem(builder(), Blocks.EXPOSED_COPPER));
+ public static final Item WEATHERED_COPPER = register(new BlockItem(builder(), Blocks.WEATHERED_COPPER));
+ public static final Item OXIDIZED_COPPER = register(new BlockItem(builder(), Blocks.OXIDIZED_COPPER));
+ public static final Item CHISELED_COPPER = register(new BlockItem(builder(), Blocks.CHISELED_COPPER));
+ public static final Item EXPOSED_CHISELED_COPPER = register(new BlockItem(builder(), Blocks.EXPOSED_CHISELED_COPPER));
+ public static final Item WEATHERED_CHISELED_COPPER = register(new BlockItem(builder(), Blocks.WEATHERED_CHISELED_COPPER));
+ public static final Item OXIDIZED_CHISELED_COPPER = register(new BlockItem(builder(), Blocks.OXIDIZED_CHISELED_COPPER));
+ public static final Item CUT_COPPER = register(new BlockItem(builder(), Blocks.CUT_COPPER));
+ public static final Item EXPOSED_CUT_COPPER = register(new BlockItem(builder(), Blocks.EXPOSED_CUT_COPPER));
+ public static final Item WEATHERED_CUT_COPPER = register(new BlockItem(builder(), Blocks.WEATHERED_CUT_COPPER));
+ public static final Item OXIDIZED_CUT_COPPER = register(new BlockItem(builder(), Blocks.OXIDIZED_CUT_COPPER));
+ public static final Item CUT_COPPER_STAIRS = register(new BlockItem(builder(), Blocks.CUT_COPPER_STAIRS));
+ public static final Item EXPOSED_CUT_COPPER_STAIRS = register(new BlockItem(builder(), Blocks.EXPOSED_CUT_COPPER_STAIRS));
+ public static final Item WEATHERED_CUT_COPPER_STAIRS = register(new BlockItem(builder(), Blocks.WEATHERED_CUT_COPPER_STAIRS));
+ public static final Item OXIDIZED_CUT_COPPER_STAIRS = register(new BlockItem(builder(), Blocks.OXIDIZED_CUT_COPPER_STAIRS));
+ public static final Item CUT_COPPER_SLAB = register(new BlockItem(builder(), Blocks.CUT_COPPER_SLAB));
+ public static final Item EXPOSED_CUT_COPPER_SLAB = register(new BlockItem(builder(), Blocks.EXPOSED_CUT_COPPER_SLAB));
+ public static final Item WEATHERED_CUT_COPPER_SLAB = register(new BlockItem(builder(), Blocks.WEATHERED_CUT_COPPER_SLAB));
+ public static final Item OXIDIZED_CUT_COPPER_SLAB = register(new BlockItem(builder(), Blocks.OXIDIZED_CUT_COPPER_SLAB));
+ public static final Item WAXED_COPPER_BLOCK = register(new BlockItem(builder(), Blocks.WAXED_COPPER_BLOCK));
+ public static final Item WAXED_EXPOSED_COPPER = register(new BlockItem(builder(), Blocks.WAXED_EXPOSED_COPPER));
+ public static final Item WAXED_WEATHERED_COPPER = register(new BlockItem(builder(), Blocks.WAXED_WEATHERED_COPPER));
+ public static final Item WAXED_OXIDIZED_COPPER = register(new BlockItem(builder(), Blocks.WAXED_OXIDIZED_COPPER));
+ public static final Item WAXED_CHISELED_COPPER = register(new BlockItem(builder(), Blocks.WAXED_CHISELED_COPPER));
+ public static final Item WAXED_EXPOSED_CHISELED_COPPER = register(new BlockItem(builder(), Blocks.WAXED_EXPOSED_CHISELED_COPPER));
+ public static final Item WAXED_WEATHERED_CHISELED_COPPER = register(new BlockItem(builder(), Blocks.WAXED_WEATHERED_CHISELED_COPPER));
+ public static final Item WAXED_OXIDIZED_CHISELED_COPPER = register(new BlockItem(builder(), Blocks.WAXED_OXIDIZED_CHISELED_COPPER));
+ public static final Item WAXED_CUT_COPPER = register(new BlockItem(builder(), Blocks.WAXED_CUT_COPPER));
+ public static final Item WAXED_EXPOSED_CUT_COPPER = register(new BlockItem(builder(), Blocks.WAXED_EXPOSED_CUT_COPPER));
+ public static final Item WAXED_WEATHERED_CUT_COPPER = register(new BlockItem(builder(), Blocks.WAXED_WEATHERED_CUT_COPPER));
+ public static final Item WAXED_OXIDIZED_CUT_COPPER = register(new BlockItem(builder(), Blocks.WAXED_OXIDIZED_CUT_COPPER));
+ public static final Item WAXED_CUT_COPPER_STAIRS = register(new BlockItem(builder(), Blocks.WAXED_CUT_COPPER_STAIRS));
+ public static final Item WAXED_EXPOSED_CUT_COPPER_STAIRS = register(new BlockItem(builder(), Blocks.WAXED_EXPOSED_CUT_COPPER_STAIRS));
+ public static final Item WAXED_WEATHERED_CUT_COPPER_STAIRS = register(new BlockItem(builder(), Blocks.WAXED_WEATHERED_CUT_COPPER_STAIRS));
+ public static final Item WAXED_OXIDIZED_CUT_COPPER_STAIRS = register(new BlockItem(builder(), Blocks.WAXED_OXIDIZED_CUT_COPPER_STAIRS));
+ public static final Item WAXED_CUT_COPPER_SLAB = register(new BlockItem(builder(), Blocks.WAXED_CUT_COPPER_SLAB));
+ public static final Item WAXED_EXPOSED_CUT_COPPER_SLAB = register(new BlockItem(builder(), Blocks.WAXED_EXPOSED_CUT_COPPER_SLAB));
+ public static final Item WAXED_WEATHERED_CUT_COPPER_SLAB = register(new BlockItem(builder(), Blocks.WAXED_WEATHERED_CUT_COPPER_SLAB));
+ public static final Item WAXED_OXIDIZED_CUT_COPPER_SLAB = register(new BlockItem(builder(), Blocks.WAXED_OXIDIZED_CUT_COPPER_SLAB));
+ public static final Item OAK_LOG = register(new BlockItem(builder(), Blocks.OAK_LOG));
+ public static final Item SPRUCE_LOG = register(new BlockItem(builder(), Blocks.SPRUCE_LOG));
+ public static final Item BIRCH_LOG = register(new BlockItem(builder(), Blocks.BIRCH_LOG));
+ public static final Item JUNGLE_LOG = register(new BlockItem(builder(), Blocks.JUNGLE_LOG));
+ public static final Item ACACIA_LOG = register(new BlockItem(builder(), Blocks.ACACIA_LOG));
+ public static final Item CHERRY_LOG = register(new BlockItem(builder(), Blocks.CHERRY_LOG));
+ public static final Item DARK_OAK_LOG = register(new BlockItem(builder(), Blocks.DARK_OAK_LOG));
+ public static final Item MANGROVE_LOG = register(new BlockItem(builder(), Blocks.MANGROVE_LOG));
+ public static final Item MANGROVE_ROOTS = register(new BlockItem(builder(), Blocks.MANGROVE_ROOTS));
+ public static final Item MUDDY_MANGROVE_ROOTS = register(new BlockItem(builder(), Blocks.MUDDY_MANGROVE_ROOTS));
+ public static final Item CRIMSON_STEM = register(new BlockItem(builder(), Blocks.CRIMSON_STEM));
+ public static final Item WARPED_STEM = register(new BlockItem(builder(), Blocks.WARPED_STEM));
+ public static final Item BAMBOO_BLOCK = register(new BlockItem(builder(), Blocks.BAMBOO_BLOCK));
+ public static final Item STRIPPED_OAK_LOG = register(new BlockItem(builder(), Blocks.STRIPPED_OAK_LOG));
+ public static final Item STRIPPED_SPRUCE_LOG = register(new BlockItem(builder(), Blocks.STRIPPED_SPRUCE_LOG));
+ public static final Item STRIPPED_BIRCH_LOG = register(new BlockItem(builder(), Blocks.STRIPPED_BIRCH_LOG));
+ public static final Item STRIPPED_JUNGLE_LOG = register(new BlockItem(builder(), Blocks.STRIPPED_JUNGLE_LOG));
+ public static final Item STRIPPED_ACACIA_LOG = register(new BlockItem(builder(), Blocks.STRIPPED_ACACIA_LOG));
+ public static final Item STRIPPED_CHERRY_LOG = register(new BlockItem(builder(), Blocks.STRIPPED_CHERRY_LOG));
+ public static final Item STRIPPED_DARK_OAK_LOG = register(new BlockItem(builder(), Blocks.STRIPPED_DARK_OAK_LOG));
+ public static final Item STRIPPED_MANGROVE_LOG = register(new BlockItem(builder(), Blocks.STRIPPED_MANGROVE_LOG));
+ public static final Item STRIPPED_CRIMSON_STEM = register(new BlockItem(builder(), Blocks.STRIPPED_CRIMSON_STEM));
+ public static final Item STRIPPED_WARPED_STEM = register(new BlockItem(builder(), Blocks.STRIPPED_WARPED_STEM));
+ public static final Item STRIPPED_OAK_WOOD = register(new BlockItem(builder(), Blocks.STRIPPED_OAK_WOOD));
+ public static final Item STRIPPED_SPRUCE_WOOD = register(new BlockItem(builder(), Blocks.STRIPPED_SPRUCE_WOOD));
+ public static final Item STRIPPED_BIRCH_WOOD = register(new BlockItem(builder(), Blocks.STRIPPED_BIRCH_WOOD));
+ public static final Item STRIPPED_JUNGLE_WOOD = register(new BlockItem(builder(), Blocks.STRIPPED_JUNGLE_WOOD));
+ public static final Item STRIPPED_ACACIA_WOOD = register(new BlockItem(builder(), Blocks.STRIPPED_ACACIA_WOOD));
+ public static final Item STRIPPED_CHERRY_WOOD = register(new BlockItem(builder(), Blocks.STRIPPED_CHERRY_WOOD));
+ public static final Item STRIPPED_DARK_OAK_WOOD = register(new BlockItem(builder(), Blocks.STRIPPED_DARK_OAK_WOOD));
+ public static final Item STRIPPED_MANGROVE_WOOD = register(new BlockItem(builder(), Blocks.STRIPPED_MANGROVE_WOOD));
+ public static final Item STRIPPED_CRIMSON_HYPHAE = register(new BlockItem(builder(), Blocks.STRIPPED_CRIMSON_HYPHAE));
+ public static final Item STRIPPED_WARPED_HYPHAE = register(new BlockItem(builder(), Blocks.STRIPPED_WARPED_HYPHAE));
+ public static final Item STRIPPED_BAMBOO_BLOCK = register(new BlockItem(builder(), Blocks.STRIPPED_BAMBOO_BLOCK));
+ public static final Item OAK_WOOD = register(new BlockItem(builder(), Blocks.OAK_WOOD));
+ public static final Item SPRUCE_WOOD = register(new BlockItem(builder(), Blocks.SPRUCE_WOOD));
+ public static final Item BIRCH_WOOD = register(new BlockItem(builder(), Blocks.BIRCH_WOOD));
+ public static final Item JUNGLE_WOOD = register(new BlockItem(builder(), Blocks.JUNGLE_WOOD));
+ public static final Item ACACIA_WOOD = register(new BlockItem(builder(), Blocks.ACACIA_WOOD));
+ public static final Item CHERRY_WOOD = register(new BlockItem(builder(), Blocks.CHERRY_WOOD));
+ public static final Item DARK_OAK_WOOD = register(new BlockItem(builder(), Blocks.DARK_OAK_WOOD));
+ public static final Item MANGROVE_WOOD = register(new BlockItem(builder(), Blocks.MANGROVE_WOOD));
+ public static final Item CRIMSON_HYPHAE = register(new BlockItem(builder(), Blocks.CRIMSON_HYPHAE));
+ public static final Item WARPED_HYPHAE = register(new BlockItem(builder(), Blocks.WARPED_HYPHAE));
+ public static final Item OAK_LEAVES = register(new BlockItem(builder(), Blocks.OAK_LEAVES));
+ public static final Item SPRUCE_LEAVES = register(new BlockItem(builder(), Blocks.SPRUCE_LEAVES));
+ public static final Item BIRCH_LEAVES = register(new BlockItem(builder(), Blocks.BIRCH_LEAVES));
+ public static final Item JUNGLE_LEAVES = register(new BlockItem(builder(), Blocks.JUNGLE_LEAVES));
+ public static final Item ACACIA_LEAVES = register(new BlockItem(builder(), Blocks.ACACIA_LEAVES));
+ public static final Item CHERRY_LEAVES = register(new BlockItem(builder(), Blocks.CHERRY_LEAVES));
+ public static final Item DARK_OAK_LEAVES = register(new BlockItem(builder(), Blocks.DARK_OAK_LEAVES));
+ public static final Item MANGROVE_LEAVES = register(new BlockItem(builder(), Blocks.MANGROVE_LEAVES));
+ public static final Item AZALEA_LEAVES = register(new BlockItem(builder(), Blocks.AZALEA_LEAVES));
+ public static final Item FLOWERING_AZALEA_LEAVES = register(new BlockItem(builder(), Blocks.FLOWERING_AZALEA_LEAVES));
+ public static final Item SPONGE = register(new BlockItem(builder(), Blocks.SPONGE));
+ public static final Item WET_SPONGE = register(new BlockItem(builder(), Blocks.WET_SPONGE));
+ public static final Item GLASS = register(new BlockItem(builder(), Blocks.GLASS));
+ public static final Item TINTED_GLASS = register(new BlockItem(builder(), Blocks.TINTED_GLASS));
+ public static final Item LAPIS_BLOCK = register(new BlockItem(builder(), Blocks.LAPIS_BLOCK));
+ public static final Item SANDSTONE = register(new BlockItem(builder(), Blocks.SANDSTONE));
+ public static final Item CHISELED_SANDSTONE = register(new BlockItem(builder(), Blocks.CHISELED_SANDSTONE));
+ public static final Item CUT_SANDSTONE = register(new BlockItem(builder(), Blocks.CUT_SANDSTONE));
+ public static final Item COBWEB = register(new BlockItem(builder(), Blocks.COBWEB));
+ public static final Item SHORT_GRASS = register(new BlockItem(builder(), Blocks.SHORT_GRASS));
+ public static final Item FERN = register(new BlockItem(builder(), Blocks.FERN));
+ public static final Item AZALEA = register(new BlockItem(builder(), Blocks.AZALEA));
+ public static final Item FLOWERING_AZALEA = register(new BlockItem(builder(), Blocks.FLOWERING_AZALEA));
+ public static final Item DEAD_BUSH = register(new BlockItem(builder(), Blocks.DEAD_BUSH));
+ public static final Item SEAGRASS = register(new BlockItem(builder(), Blocks.SEAGRASS));
+ public static final Item SEA_PICKLE = register(new BlockItem(builder(), Blocks.SEA_PICKLE));
+ public static final Item WHITE_WOOL = register(new BlockItem(builder(), Blocks.WHITE_WOOL));
+ public static final Item ORANGE_WOOL = register(new BlockItem(builder(), Blocks.ORANGE_WOOL));
+ public static final Item MAGENTA_WOOL = register(new BlockItem(builder(), Blocks.MAGENTA_WOOL));
+ public static final Item LIGHT_BLUE_WOOL = register(new BlockItem(builder(), Blocks.LIGHT_BLUE_WOOL));
+ public static final Item YELLOW_WOOL = register(new BlockItem(builder(), Blocks.YELLOW_WOOL));
+ public static final Item LIME_WOOL = register(new BlockItem(builder(), Blocks.LIME_WOOL));
+ public static final Item PINK_WOOL = register(new BlockItem(builder(), Blocks.PINK_WOOL));
+ public static final Item GRAY_WOOL = register(new BlockItem(builder(), Blocks.GRAY_WOOL));
+ public static final Item LIGHT_GRAY_WOOL = register(new BlockItem(builder(), Blocks.LIGHT_GRAY_WOOL));
+ public static final Item CYAN_WOOL = register(new BlockItem(builder(), Blocks.CYAN_WOOL));
+ public static final Item PURPLE_WOOL = register(new BlockItem(builder(), Blocks.PURPLE_WOOL));
+ public static final Item BLUE_WOOL = register(new BlockItem(builder(), Blocks.BLUE_WOOL));
+ public static final Item BROWN_WOOL = register(new BlockItem(builder(), Blocks.BROWN_WOOL));
+ public static final Item GREEN_WOOL = register(new BlockItem(builder(), Blocks.GREEN_WOOL));
+ public static final Item RED_WOOL = register(new BlockItem(builder(), Blocks.RED_WOOL));
+ public static final Item BLACK_WOOL = register(new BlockItem(builder(), Blocks.BLACK_WOOL));
+ public static final Item DANDELION = register(new BlockItem(builder(), Blocks.DANDELION));
+ public static final Item POPPY = register(new BlockItem(builder(), Blocks.POPPY));
+ public static final Item BLUE_ORCHID = register(new BlockItem(builder(), Blocks.BLUE_ORCHID));
+ public static final Item ALLIUM = register(new BlockItem(builder(), Blocks.ALLIUM));
+ public static final Item AZURE_BLUET = register(new BlockItem(builder(), Blocks.AZURE_BLUET));
+ public static final Item RED_TULIP = register(new BlockItem(builder(), Blocks.RED_TULIP));
+ public static final Item ORANGE_TULIP = register(new BlockItem(builder(), Blocks.ORANGE_TULIP));
+ public static final Item WHITE_TULIP = register(new BlockItem(builder(), Blocks.WHITE_TULIP));
+ public static final Item PINK_TULIP = register(new BlockItem(builder(), Blocks.PINK_TULIP));
+ public static final Item OXEYE_DAISY = register(new BlockItem(builder(), Blocks.OXEYE_DAISY));
+ public static final Item CORNFLOWER = register(new BlockItem(builder(), Blocks.CORNFLOWER));
+ public static final Item LILY_OF_THE_VALLEY = register(new BlockItem(builder(), Blocks.LILY_OF_THE_VALLEY));
+ public static final Item WITHER_ROSE = register(new BlockItem(builder(), Blocks.WITHER_ROSE));
+ public static final Item TORCHFLOWER = register(new BlockItem(builder(), Blocks.TORCHFLOWER));
+ public static final Item PITCHER_PLANT = register(new BlockItem(builder(), Blocks.PITCHER_PLANT));
+ public static final Item SPORE_BLOSSOM = register(new BlockItem(builder(), Blocks.SPORE_BLOSSOM));
+ public static final Item BROWN_MUSHROOM = register(new BlockItem(builder(), Blocks.BROWN_MUSHROOM));
+ public static final Item RED_MUSHROOM = register(new BlockItem(builder(), Blocks.RED_MUSHROOM));
+ public static final Item CRIMSON_FUNGUS = register(new BlockItem(builder(), Blocks.CRIMSON_FUNGUS));
+ public static final Item WARPED_FUNGUS = register(new BlockItem(builder(), Blocks.WARPED_FUNGUS));
+ public static final Item CRIMSON_ROOTS = register(new BlockItem(builder(), Blocks.CRIMSON_ROOTS));
+ public static final Item WARPED_ROOTS = register(new BlockItem(builder(), Blocks.WARPED_ROOTS));
+ public static final Item NETHER_SPROUTS = register(new BlockItem(builder(), Blocks.NETHER_SPROUTS));
+ public static final Item WEEPING_VINES = register(new BlockItem(builder(), Blocks.WEEPING_VINES));
+ public static final Item TWISTING_VINES = register(new BlockItem(builder(), Blocks.TWISTING_VINES));
+ public static final Item SUGAR_CANE = register(new BlockItem(builder(), Blocks.SUGAR_CANE));
+ public static final Item KELP = register(new BlockItem(builder(), Blocks.KELP));
+ public static final Item MOSS_CARPET = register(new BlockItem(builder(), Blocks.MOSS_CARPET));
+ public static final Item PINK_PETALS = register(new BlockItem(builder(), Blocks.PINK_PETALS));
+ public static final Item MOSS_BLOCK = register(new BlockItem(builder(), Blocks.MOSS_BLOCK));
+ public static final Item HANGING_ROOTS = register(new BlockItem(builder(), Blocks.HANGING_ROOTS));
+ public static final Item BIG_DRIPLEAF = register(new BlockItem(builder(), Blocks.BIG_DRIPLEAF, Blocks.BIG_DRIPLEAF_STEM));
+ public static final Item SMALL_DRIPLEAF = register(new BlockItem(builder(), Blocks.SMALL_DRIPLEAF));
+ public static final Item BAMBOO = register(new BlockItem(builder(), Blocks.BAMBOO));
+ public static final Item OAK_SLAB = register(new BlockItem(builder(), Blocks.OAK_SLAB));
+ public static final Item SPRUCE_SLAB = register(new BlockItem(builder(), Blocks.SPRUCE_SLAB));
+ public static final Item BIRCH_SLAB = register(new BlockItem(builder(), Blocks.BIRCH_SLAB));
+ public static final Item JUNGLE_SLAB = register(new BlockItem(builder(), Blocks.JUNGLE_SLAB));
+ public static final Item ACACIA_SLAB = register(new BlockItem(builder(), Blocks.ACACIA_SLAB));
+ public static final Item CHERRY_SLAB = register(new BlockItem(builder(), Blocks.CHERRY_SLAB));
+ public static final Item DARK_OAK_SLAB = register(new BlockItem(builder(), Blocks.DARK_OAK_SLAB));
+ public static final Item MANGROVE_SLAB = register(new BlockItem(builder(), Blocks.MANGROVE_SLAB));
+ public static final Item BAMBOO_SLAB = register(new BlockItem(builder(), Blocks.BAMBOO_SLAB));
+ public static final Item BAMBOO_MOSAIC_SLAB = register(new BlockItem(builder(), Blocks.BAMBOO_MOSAIC_SLAB));
+ public static final Item CRIMSON_SLAB = register(new BlockItem(builder(), Blocks.CRIMSON_SLAB));
+ public static final Item WARPED_SLAB = register(new BlockItem(builder(), Blocks.WARPED_SLAB));
+ public static final Item STONE_SLAB = register(new BlockItem(builder(), Blocks.STONE_SLAB));
+ public static final Item SMOOTH_STONE_SLAB = register(new BlockItem(builder(), Blocks.SMOOTH_STONE_SLAB));
+ public static final Item SANDSTONE_SLAB = register(new BlockItem(builder(), Blocks.SANDSTONE_SLAB));
+ public static final Item CUT_SANDSTONE_SLAB = register(new BlockItem(builder(), Blocks.CUT_SANDSTONE_SLAB));
+ public static final Item PETRIFIED_OAK_SLAB = register(new BlockItem(builder(), Blocks.PETRIFIED_OAK_SLAB));
+ public static final Item COBBLESTONE_SLAB = register(new BlockItem(builder(), Blocks.COBBLESTONE_SLAB));
+ public static final Item BRICK_SLAB = register(new BlockItem(builder(), Blocks.BRICK_SLAB));
+ public static final Item STONE_BRICK_SLAB = register(new BlockItem(builder(), Blocks.STONE_BRICK_SLAB));
+ public static final Item MUD_BRICK_SLAB = register(new BlockItem(builder(), Blocks.MUD_BRICK_SLAB));
+ public static final Item NETHER_BRICK_SLAB = register(new BlockItem(builder(), Blocks.NETHER_BRICK_SLAB));
+ public static final Item QUARTZ_SLAB = register(new BlockItem(builder(), Blocks.QUARTZ_SLAB));
+ public static final Item RED_SANDSTONE_SLAB = register(new BlockItem(builder(), Blocks.RED_SANDSTONE_SLAB));
+ public static final Item CUT_RED_SANDSTONE_SLAB = register(new BlockItem(builder(), Blocks.CUT_RED_SANDSTONE_SLAB));
+ public static final Item PURPUR_SLAB = register(new BlockItem(builder(), Blocks.PURPUR_SLAB));
+ public static final Item PRISMARINE_SLAB = register(new BlockItem(builder(), Blocks.PRISMARINE_SLAB));
+ public static final Item PRISMARINE_BRICK_SLAB = register(new BlockItem(builder(), Blocks.PRISMARINE_BRICK_SLAB));
+ public static final Item DARK_PRISMARINE_SLAB = register(new BlockItem(builder(), Blocks.DARK_PRISMARINE_SLAB));
+ public static final Item SMOOTH_QUARTZ = register(new BlockItem(builder(), Blocks.SMOOTH_QUARTZ));
+ public static final Item SMOOTH_RED_SANDSTONE = register(new BlockItem(builder(), Blocks.SMOOTH_RED_SANDSTONE));
+ public static final Item SMOOTH_SANDSTONE = register(new BlockItem(builder(), Blocks.SMOOTH_SANDSTONE));
+ public static final Item SMOOTH_STONE = register(new BlockItem(builder(), Blocks.SMOOTH_STONE));
+ public static final Item BRICKS = register(new BlockItem(builder(), Blocks.BRICKS));
+ public static final Item BOOKSHELF = register(new BlockItem(builder(), Blocks.BOOKSHELF));
+ public static final Item CHISELED_BOOKSHELF = register(new BlockItem(builder(), Blocks.CHISELED_BOOKSHELF));
+ public static final Item DECORATED_POT = register(new DecoratedPotItem(builder(), Blocks.DECORATED_POT));
+ public static final Item MOSSY_COBBLESTONE = register(new BlockItem(builder(), Blocks.MOSSY_COBBLESTONE));
+ public static final Item OBSIDIAN = register(new BlockItem(builder(), Blocks.OBSIDIAN));
+ public static final Item TORCH = register(new BlockItem(builder(), Blocks.TORCH, Blocks.WALL_TORCH));
+ public static final Item END_ROD = register(new BlockItem(builder(), Blocks.END_ROD));
+ public static final Item CHORUS_PLANT = register(new BlockItem(builder(), Blocks.CHORUS_PLANT));
+ public static final Item CHORUS_FLOWER = register(new BlockItem(builder(), Blocks.CHORUS_FLOWER));
+ public static final Item PURPUR_BLOCK = register(new BlockItem(builder(), Blocks.PURPUR_BLOCK));
+ public static final Item PURPUR_PILLAR = register(new BlockItem(builder(), Blocks.PURPUR_PILLAR));
+ public static final Item PURPUR_STAIRS = register(new BlockItem(builder(), Blocks.PURPUR_STAIRS));
+ public static final Item SPAWNER = register(new BlockItem(builder(), Blocks.SPAWNER));
+ public static final Item CHEST = register(new BlockItem(builder(), Blocks.CHEST));
+ public static final Item CRAFTING_TABLE = register(new BlockItem(builder(), Blocks.CRAFTING_TABLE));
+ public static final Item FARMLAND = register(new BlockItem(builder(), Blocks.FARMLAND));
+ public static final Item FURNACE = register(new BlockItem(builder(), Blocks.FURNACE));
+ public static final Item LADDER = register(new BlockItem(builder(), Blocks.LADDER));
+ public static final Item COBBLESTONE_STAIRS = register(new BlockItem(builder(), Blocks.COBBLESTONE_STAIRS));
+ public static final Item SNOW = register(new BlockItem(builder(), Blocks.SNOW));
+ public static final Item ICE = register(new BlockItem(builder(), Blocks.ICE));
+ public static final Item SNOW_BLOCK = register(new BlockItem(builder(), Blocks.SNOW_BLOCK));
+ public static final Item CACTUS = register(new BlockItem(builder(), Blocks.CACTUS));
+ public static final Item CLAY = register(new BlockItem(builder(), Blocks.CLAY));
+ public static final Item JUKEBOX = register(new BlockItem(builder(), Blocks.JUKEBOX));
+ public static final Item OAK_FENCE = register(new BlockItem(builder(), Blocks.OAK_FENCE));
+ public static final Item SPRUCE_FENCE = register(new BlockItem(builder(), Blocks.SPRUCE_FENCE));
+ public static final Item BIRCH_FENCE = register(new BlockItem(builder(), Blocks.BIRCH_FENCE));
+ public static final Item JUNGLE_FENCE = register(new BlockItem(builder(), Blocks.JUNGLE_FENCE));
+ public static final Item ACACIA_FENCE = register(new BlockItem(builder(), Blocks.ACACIA_FENCE));
+ public static final Item CHERRY_FENCE = register(new BlockItem(builder(), Blocks.CHERRY_FENCE));
+ public static final Item DARK_OAK_FENCE = register(new BlockItem(builder(), Blocks.DARK_OAK_FENCE));
+ public static final Item MANGROVE_FENCE = register(new BlockItem(builder(), Blocks.MANGROVE_FENCE));
+ public static final Item BAMBOO_FENCE = register(new BlockItem(builder(), Blocks.BAMBOO_FENCE));
+ public static final Item CRIMSON_FENCE = register(new BlockItem(builder(), Blocks.CRIMSON_FENCE));
+ public static final Item WARPED_FENCE = register(new BlockItem(builder(), Blocks.WARPED_FENCE));
+ public static final Item PUMPKIN = register(new BlockItem(builder(), Blocks.PUMPKIN));
+ public static final Item CARVED_PUMPKIN = register(new BlockItem(builder(), Blocks.CARVED_PUMPKIN));
+ public static final Item JACK_O_LANTERN = register(new BlockItem(builder(), Blocks.JACK_O_LANTERN));
+ public static final Item NETHERRACK = register(new BlockItem(builder(), Blocks.NETHERRACK));
+ public static final Item SOUL_SAND = register(new BlockItem(builder(), Blocks.SOUL_SAND));
+ public static final Item SOUL_SOIL = register(new BlockItem(builder(), Blocks.SOUL_SOIL));
+ public static final Item BASALT = register(new BlockItem(builder(), Blocks.BASALT));
+ public static final Item POLISHED_BASALT = register(new BlockItem(builder(), Blocks.POLISHED_BASALT));
+ public static final Item SMOOTH_BASALT = register(new BlockItem(builder(), Blocks.SMOOTH_BASALT));
+ public static final Item SOUL_TORCH = register(new BlockItem(builder(), Blocks.SOUL_TORCH, Blocks.SOUL_WALL_TORCH));
+ public static final Item GLOWSTONE = register(new BlockItem(builder(), Blocks.GLOWSTONE));
+ public static final Item INFESTED_STONE = register(new BlockItem(builder(), Blocks.INFESTED_STONE));
+ public static final Item INFESTED_COBBLESTONE = register(new BlockItem(builder(), Blocks.INFESTED_COBBLESTONE));
+ public static final Item INFESTED_STONE_BRICKS = register(new BlockItem(builder(), Blocks.INFESTED_STONE_BRICKS));
+ public static final Item INFESTED_MOSSY_STONE_BRICKS = register(new BlockItem(builder(), Blocks.INFESTED_MOSSY_STONE_BRICKS));
+ public static final Item INFESTED_CRACKED_STONE_BRICKS = register(new BlockItem(builder(), Blocks.INFESTED_CRACKED_STONE_BRICKS));
+ public static final Item INFESTED_CHISELED_STONE_BRICKS = register(new BlockItem(builder(), Blocks.INFESTED_CHISELED_STONE_BRICKS));
+ public static final Item INFESTED_DEEPSLATE = register(new BlockItem(builder(), Blocks.INFESTED_DEEPSLATE));
+ public static final Item STONE_BRICKS = register(new BlockItem(builder(), Blocks.STONE_BRICKS));
+ public static final Item MOSSY_STONE_BRICKS = register(new BlockItem(builder(), Blocks.MOSSY_STONE_BRICKS));
+ public static final Item CRACKED_STONE_BRICKS = register(new BlockItem(builder(), Blocks.CRACKED_STONE_BRICKS));
+ public static final Item CHISELED_STONE_BRICKS = register(new BlockItem(builder(), Blocks.CHISELED_STONE_BRICKS));
+ public static final Item PACKED_MUD = register(new BlockItem(builder(), Blocks.PACKED_MUD));
+ public static final Item MUD_BRICKS = register(new BlockItem(builder(), Blocks.MUD_BRICKS));
+ public static final Item DEEPSLATE_BRICKS = register(new BlockItem(builder(), Blocks.DEEPSLATE_BRICKS));
+ public static final Item CRACKED_DEEPSLATE_BRICKS = register(new BlockItem(builder(), Blocks.CRACKED_DEEPSLATE_BRICKS));
+ public static final Item DEEPSLATE_TILES = register(new BlockItem(builder(), Blocks.DEEPSLATE_TILES));
+ public static final Item CRACKED_DEEPSLATE_TILES = register(new BlockItem(builder(), Blocks.CRACKED_DEEPSLATE_TILES));
+ public static final Item CHISELED_DEEPSLATE = register(new BlockItem(builder(), Blocks.CHISELED_DEEPSLATE));
+ public static final Item REINFORCED_DEEPSLATE = register(new BlockItem(builder(), Blocks.REINFORCED_DEEPSLATE));
+ public static final Item BROWN_MUSHROOM_BLOCK = register(new BlockItem(builder(), Blocks.BROWN_MUSHROOM_BLOCK));
+ public static final Item RED_MUSHROOM_BLOCK = register(new BlockItem(builder(), Blocks.RED_MUSHROOM_BLOCK));
+ public static final Item MUSHROOM_STEM = register(new BlockItem(builder(), Blocks.MUSHROOM_STEM));
+ public static final Item IRON_BARS = register(new BlockItem(builder(), Blocks.IRON_BARS));
+ public static final Item CHAIN = register(new BlockItem(builder(), Blocks.CHAIN));
+ public static final Item GLASS_PANE = register(new BlockItem(builder(), Blocks.GLASS_PANE));
+ public static final Item MELON = register(new BlockItem(builder(), Blocks.MELON));
+ public static final Item VINE = register(new BlockItem(builder(), Blocks.VINE));
+ public static final Item GLOW_LICHEN = register(new BlockItem(builder(), Blocks.GLOW_LICHEN));
+ public static final Item BRICK_STAIRS = register(new BlockItem(builder(), Blocks.BRICK_STAIRS));
+ public static final Item STONE_BRICK_STAIRS = register(new BlockItem(builder(), Blocks.STONE_BRICK_STAIRS));
+ public static final Item MUD_BRICK_STAIRS = register(new BlockItem(builder(), Blocks.MUD_BRICK_STAIRS));
+ public static final Item MYCELIUM = register(new BlockItem(builder(), Blocks.MYCELIUM));
+ public static final Item LILY_PAD = register(new BlockItem(builder(), Blocks.LILY_PAD));
+ public static final Item NETHER_BRICKS = register(new BlockItem(builder(), Blocks.NETHER_BRICKS));
+ public static final Item CRACKED_NETHER_BRICKS = register(new BlockItem(builder(), Blocks.CRACKED_NETHER_BRICKS));
+ public static final Item CHISELED_NETHER_BRICKS = register(new BlockItem(builder(), Blocks.CHISELED_NETHER_BRICKS));
+ public static final Item NETHER_BRICK_FENCE = register(new BlockItem(builder(), Blocks.NETHER_BRICK_FENCE));
+ public static final Item NETHER_BRICK_STAIRS = register(new BlockItem(builder(), Blocks.NETHER_BRICK_STAIRS));
+ public static final Item SCULK = register(new BlockItem(builder(), Blocks.SCULK));
+ public static final Item SCULK_VEIN = register(new BlockItem(builder(), Blocks.SCULK_VEIN));
+ public static final Item SCULK_CATALYST = register(new BlockItem(builder(), Blocks.SCULK_CATALYST));
+ public static final Item SCULK_SHRIEKER = register(new BlockItem(builder(), Blocks.SCULK_SHRIEKER));
+ public static final Item ENCHANTING_TABLE = register(new BlockItem(builder(), Blocks.ENCHANTING_TABLE));
+ public static final Item END_PORTAL_FRAME = register(new BlockItem(builder(), Blocks.END_PORTAL_FRAME));
+ public static final Item END_STONE = register(new BlockItem(builder(), Blocks.END_STONE));
+ public static final Item END_STONE_BRICKS = register(new BlockItem(builder(), Blocks.END_STONE_BRICKS));
+ public static final Item DRAGON_EGG = register(new BlockItem(builder(), Blocks.DRAGON_EGG));
+ public static final Item SANDSTONE_STAIRS = register(new BlockItem(builder(), Blocks.SANDSTONE_STAIRS));
+ public static final Item ENDER_CHEST = register(new BlockItem(builder(), Blocks.ENDER_CHEST));
+ public static final Item EMERALD_BLOCK = register(new BlockItem(builder(), Blocks.EMERALD_BLOCK));
+ public static final Item OAK_STAIRS = register(new BlockItem(builder(), Blocks.OAK_STAIRS));
+ public static final Item SPRUCE_STAIRS = register(new BlockItem(builder(), Blocks.SPRUCE_STAIRS));
+ public static final Item BIRCH_STAIRS = register(new BlockItem(builder(), Blocks.BIRCH_STAIRS));
+ public static final Item JUNGLE_STAIRS = register(new BlockItem(builder(), Blocks.JUNGLE_STAIRS));
+ public static final Item ACACIA_STAIRS = register(new BlockItem(builder(), Blocks.ACACIA_STAIRS));
+ public static final Item CHERRY_STAIRS = register(new BlockItem(builder(), Blocks.CHERRY_STAIRS));
+ public static final Item DARK_OAK_STAIRS = register(new BlockItem(builder(), Blocks.DARK_OAK_STAIRS));
+ public static final Item MANGROVE_STAIRS = register(new BlockItem(builder(), Blocks.MANGROVE_STAIRS));
+ public static final Item BAMBOO_STAIRS = register(new BlockItem(builder(), Blocks.BAMBOO_STAIRS));
+ public static final Item BAMBOO_MOSAIC_STAIRS = register(new BlockItem(builder(), Blocks.BAMBOO_MOSAIC_STAIRS));
+ public static final Item CRIMSON_STAIRS = register(new BlockItem(builder(), Blocks.CRIMSON_STAIRS));
+ public static final Item WARPED_STAIRS = register(new BlockItem(builder(), Blocks.WARPED_STAIRS));
+ public static final Item COMMAND_BLOCK = register(new BlockItem(builder(), Blocks.COMMAND_BLOCK));
+ public static final Item BEACON = register(new BlockItem(builder(), Blocks.BEACON));
+ public static final Item COBBLESTONE_WALL = register(new BlockItem(builder(), Blocks.COBBLESTONE_WALL));
+ public static final Item MOSSY_COBBLESTONE_WALL = register(new BlockItem(builder(), Blocks.MOSSY_COBBLESTONE_WALL));
+ public static final Item BRICK_WALL = register(new BlockItem(builder(), Blocks.BRICK_WALL));
+ public static final Item PRISMARINE_WALL = register(new BlockItem(builder(), Blocks.PRISMARINE_WALL));
+ public static final Item RED_SANDSTONE_WALL = register(new BlockItem(builder(), Blocks.RED_SANDSTONE_WALL));
+ public static final Item MOSSY_STONE_BRICK_WALL = register(new BlockItem(builder(), Blocks.MOSSY_STONE_BRICK_WALL));
+ public static final Item GRANITE_WALL = register(new BlockItem(builder(), Blocks.GRANITE_WALL));
+ public static final Item STONE_BRICK_WALL = register(new BlockItem(builder(), Blocks.STONE_BRICK_WALL));
+ public static final Item MUD_BRICK_WALL = register(new BlockItem(builder(), Blocks.MUD_BRICK_WALL));
+ public static final Item NETHER_BRICK_WALL = register(new BlockItem(builder(), Blocks.NETHER_BRICK_WALL));
+ public static final Item ANDESITE_WALL = register(new BlockItem(builder(), Blocks.ANDESITE_WALL));
+ public static final Item RED_NETHER_BRICK_WALL = register(new BlockItem(builder(), Blocks.RED_NETHER_BRICK_WALL));
+ public static final Item SANDSTONE_WALL = register(new BlockItem(builder(), Blocks.SANDSTONE_WALL));
+ public static final Item END_STONE_BRICK_WALL = register(new BlockItem(builder(), Blocks.END_STONE_BRICK_WALL));
+ public static final Item DIORITE_WALL = register(new BlockItem(builder(), Blocks.DIORITE_WALL));
+ public static final Item BLACKSTONE_WALL = register(new BlockItem(builder(), Blocks.BLACKSTONE_WALL));
+ public static final Item POLISHED_BLACKSTONE_WALL = register(new BlockItem(builder(), Blocks.POLISHED_BLACKSTONE_WALL));
+ public static final Item POLISHED_BLACKSTONE_BRICK_WALL = register(new BlockItem(builder(), Blocks.POLISHED_BLACKSTONE_BRICK_WALL));
+ public static final Item COBBLED_DEEPSLATE_WALL = register(new BlockItem(builder(), Blocks.COBBLED_DEEPSLATE_WALL));
+ public static final Item POLISHED_DEEPSLATE_WALL = register(new BlockItem(builder(), Blocks.POLISHED_DEEPSLATE_WALL));
+ public static final Item DEEPSLATE_BRICK_WALL = register(new BlockItem(builder(), Blocks.DEEPSLATE_BRICK_WALL));
+ public static final Item DEEPSLATE_TILE_WALL = register(new BlockItem(builder(), Blocks.DEEPSLATE_TILE_WALL));
+ public static final Item ANVIL = register(new BlockItem(builder(), Blocks.ANVIL));
+ public static final Item CHIPPED_ANVIL = register(new BlockItem(builder(), Blocks.CHIPPED_ANVIL));
+ public static final Item DAMAGED_ANVIL = register(new BlockItem(builder(), Blocks.DAMAGED_ANVIL));
+ public static final Item CHISELED_QUARTZ_BLOCK = register(new BlockItem(builder(), Blocks.CHISELED_QUARTZ_BLOCK));
+ public static final Item QUARTZ_BLOCK = register(new BlockItem(builder(), Blocks.QUARTZ_BLOCK));
+ public static final Item QUARTZ_BRICKS = register(new BlockItem(builder(), Blocks.QUARTZ_BRICKS));
+ public static final Item QUARTZ_PILLAR = register(new BlockItem(builder(), Blocks.QUARTZ_PILLAR));
+ public static final Item QUARTZ_STAIRS = register(new BlockItem(builder(), Blocks.QUARTZ_STAIRS));
+ public static final Item WHITE_TERRACOTTA = register(new BlockItem(builder(), Blocks.WHITE_TERRACOTTA));
+ public static final Item ORANGE_TERRACOTTA = register(new BlockItem(builder(), Blocks.ORANGE_TERRACOTTA));
+ public static final Item MAGENTA_TERRACOTTA = register(new BlockItem(builder(), Blocks.MAGENTA_TERRACOTTA));
+ public static final Item LIGHT_BLUE_TERRACOTTA = register(new BlockItem(builder(), Blocks.LIGHT_BLUE_TERRACOTTA));
+ public static final Item YELLOW_TERRACOTTA = register(new BlockItem(builder(), Blocks.YELLOW_TERRACOTTA));
+ public static final Item LIME_TERRACOTTA = register(new BlockItem(builder(), Blocks.LIME_TERRACOTTA));
+ public static final Item PINK_TERRACOTTA = register(new BlockItem(builder(), Blocks.PINK_TERRACOTTA));
+ public static final Item GRAY_TERRACOTTA = register(new BlockItem(builder(), Blocks.GRAY_TERRACOTTA));
+ public static final Item LIGHT_GRAY_TERRACOTTA = register(new BlockItem(builder(), Blocks.LIGHT_GRAY_TERRACOTTA));
+ public static final Item CYAN_TERRACOTTA = register(new BlockItem(builder(), Blocks.CYAN_TERRACOTTA));
+ public static final Item PURPLE_TERRACOTTA = register(new BlockItem(builder(), Blocks.PURPLE_TERRACOTTA));
+ public static final Item BLUE_TERRACOTTA = register(new BlockItem(builder(), Blocks.BLUE_TERRACOTTA));
+ public static final Item BROWN_TERRACOTTA = register(new BlockItem(builder(), Blocks.BROWN_TERRACOTTA));
+ public static final Item GREEN_TERRACOTTA = register(new BlockItem(builder(), Blocks.GREEN_TERRACOTTA));
+ public static final Item RED_TERRACOTTA = register(new BlockItem(builder(), Blocks.RED_TERRACOTTA));
+ public static final Item BLACK_TERRACOTTA = register(new BlockItem(builder(), Blocks.BLACK_TERRACOTTA));
+ public static final Item BARRIER = register(new BlockItem(builder(), Blocks.BARRIER));
+ public static final Item LIGHT = register(new BlockItem(builder(), Blocks.LIGHT));
+ public static final Item HAY_BLOCK = register(new BlockItem(builder(), Blocks.HAY_BLOCK));
+ public static final Item WHITE_CARPET = register(new BlockItem(builder(), Blocks.WHITE_CARPET));
+ public static final Item ORANGE_CARPET = register(new BlockItem(builder(), Blocks.ORANGE_CARPET));
+ public static final Item MAGENTA_CARPET = register(new BlockItem(builder(), Blocks.MAGENTA_CARPET));
+ public static final Item LIGHT_BLUE_CARPET = register(new BlockItem(builder(), Blocks.LIGHT_BLUE_CARPET));
+ public static final Item YELLOW_CARPET = register(new BlockItem(builder(), Blocks.YELLOW_CARPET));
+ public static final Item LIME_CARPET = register(new BlockItem(builder(), Blocks.LIME_CARPET));
+ public static final Item PINK_CARPET = register(new BlockItem(builder(), Blocks.PINK_CARPET));
+ public static final Item GRAY_CARPET = register(new BlockItem(builder(), Blocks.GRAY_CARPET));
+ public static final Item LIGHT_GRAY_CARPET = register(new BlockItem(builder(), Blocks.LIGHT_GRAY_CARPET));
+ public static final Item CYAN_CARPET = register(new BlockItem(builder(), Blocks.CYAN_CARPET));
+ public static final Item PURPLE_CARPET = register(new BlockItem(builder(), Blocks.PURPLE_CARPET));
+ public static final Item BLUE_CARPET = register(new BlockItem(builder(), Blocks.BLUE_CARPET));
+ public static final Item BROWN_CARPET = register(new BlockItem(builder(), Blocks.BROWN_CARPET));
+ public static final Item GREEN_CARPET = register(new BlockItem(builder(), Blocks.GREEN_CARPET));
+ public static final Item RED_CARPET = register(new BlockItem(builder(), Blocks.RED_CARPET));
+ public static final Item BLACK_CARPET = register(new BlockItem(builder(), Blocks.BLACK_CARPET));
+ public static final Item TERRACOTTA = register(new BlockItem(builder(), Blocks.TERRACOTTA));
+ public static final Item PACKED_ICE = register(new BlockItem(builder(), Blocks.PACKED_ICE));
+ public static final Item DIRT_PATH = register(new BlockItem(builder(), Blocks.DIRT_PATH));
+ public static final Item SUNFLOWER = register(new BlockItem(builder(), Blocks.SUNFLOWER));
+ public static final Item LILAC = register(new BlockItem(builder(), Blocks.LILAC));
+ public static final Item ROSE_BUSH = register(new BlockItem(builder(), Blocks.ROSE_BUSH));
+ public static final Item PEONY = register(new BlockItem(builder(), Blocks.PEONY));
+ public static final Item TALL_GRASS = register(new BlockItem(builder(), Blocks.TALL_GRASS));
+ public static final Item LARGE_FERN = register(new BlockItem(builder(), Blocks.LARGE_FERN));
+ public static final Item WHITE_STAINED_GLASS = register(new BlockItem(builder(), Blocks.WHITE_STAINED_GLASS));
+ public static final Item ORANGE_STAINED_GLASS = register(new BlockItem(builder(), Blocks.ORANGE_STAINED_GLASS));
+ public static final Item MAGENTA_STAINED_GLASS = register(new BlockItem(builder(), Blocks.MAGENTA_STAINED_GLASS));
+ public static final Item LIGHT_BLUE_STAINED_GLASS = register(new BlockItem(builder(), Blocks.LIGHT_BLUE_STAINED_GLASS));
+ public static final Item YELLOW_STAINED_GLASS = register(new BlockItem(builder(), Blocks.YELLOW_STAINED_GLASS));
+ public static final Item LIME_STAINED_GLASS = register(new BlockItem(builder(), Blocks.LIME_STAINED_GLASS));
+ public static final Item PINK_STAINED_GLASS = register(new BlockItem(builder(), Blocks.PINK_STAINED_GLASS));
+ public static final Item GRAY_STAINED_GLASS = register(new BlockItem(builder(), Blocks.GRAY_STAINED_GLASS));
+ public static final Item LIGHT_GRAY_STAINED_GLASS = register(new BlockItem(builder(), Blocks.LIGHT_GRAY_STAINED_GLASS));
+ public static final Item CYAN_STAINED_GLASS = register(new BlockItem(builder(), Blocks.CYAN_STAINED_GLASS));
+ public static final Item PURPLE_STAINED_GLASS = register(new BlockItem(builder(), Blocks.PURPLE_STAINED_GLASS));
+ public static final Item BLUE_STAINED_GLASS = register(new BlockItem(builder(), Blocks.BLUE_STAINED_GLASS));
+ public static final Item BROWN_STAINED_GLASS = register(new BlockItem(builder(), Blocks.BROWN_STAINED_GLASS));
+ public static final Item GREEN_STAINED_GLASS = register(new BlockItem(builder(), Blocks.GREEN_STAINED_GLASS));
+ public static final Item RED_STAINED_GLASS = register(new BlockItem(builder(), Blocks.RED_STAINED_GLASS));
+ public static final Item BLACK_STAINED_GLASS = register(new BlockItem(builder(), Blocks.BLACK_STAINED_GLASS));
+ public static final Item WHITE_STAINED_GLASS_PANE = register(new BlockItem(builder(), Blocks.WHITE_STAINED_GLASS_PANE));
+ public static final Item ORANGE_STAINED_GLASS_PANE = register(new BlockItem(builder(), Blocks.ORANGE_STAINED_GLASS_PANE));
+ public static final Item MAGENTA_STAINED_GLASS_PANE = register(new BlockItem(builder(), Blocks.MAGENTA_STAINED_GLASS_PANE));
+ public static final Item LIGHT_BLUE_STAINED_GLASS_PANE = register(new BlockItem(builder(), Blocks.LIGHT_BLUE_STAINED_GLASS_PANE));
+ public static final Item YELLOW_STAINED_GLASS_PANE = register(new BlockItem(builder(), Blocks.YELLOW_STAINED_GLASS_PANE));
+ public static final Item LIME_STAINED_GLASS_PANE = register(new BlockItem(builder(), Blocks.LIME_STAINED_GLASS_PANE));
+ public static final Item PINK_STAINED_GLASS_PANE = register(new BlockItem(builder(), Blocks.PINK_STAINED_GLASS_PANE));
+ public static final Item GRAY_STAINED_GLASS_PANE = register(new BlockItem(builder(), Blocks.GRAY_STAINED_GLASS_PANE));
+ public static final Item LIGHT_GRAY_STAINED_GLASS_PANE = register(new BlockItem(builder(), Blocks.LIGHT_GRAY_STAINED_GLASS_PANE));
+ public static final Item CYAN_STAINED_GLASS_PANE = register(new BlockItem(builder(), Blocks.CYAN_STAINED_GLASS_PANE));
+ public static final Item PURPLE_STAINED_GLASS_PANE = register(new BlockItem(builder(), Blocks.PURPLE_STAINED_GLASS_PANE));
+ public static final Item BLUE_STAINED_GLASS_PANE = register(new BlockItem(builder(), Blocks.BLUE_STAINED_GLASS_PANE));
+ public static final Item BROWN_STAINED_GLASS_PANE = register(new BlockItem(builder(), Blocks.BROWN_STAINED_GLASS_PANE));
+ public static final Item GREEN_STAINED_GLASS_PANE = register(new BlockItem(builder(), Blocks.GREEN_STAINED_GLASS_PANE));
+ public static final Item RED_STAINED_GLASS_PANE = register(new BlockItem(builder(), Blocks.RED_STAINED_GLASS_PANE));
+ public static final Item BLACK_STAINED_GLASS_PANE = register(new BlockItem(builder(), Blocks.BLACK_STAINED_GLASS_PANE));
+ public static final Item PRISMARINE = register(new BlockItem(builder(), Blocks.PRISMARINE));
+ public static final Item PRISMARINE_BRICKS = register(new BlockItem(builder(), Blocks.PRISMARINE_BRICKS));
+ public static final Item DARK_PRISMARINE = register(new BlockItem(builder(), Blocks.DARK_PRISMARINE));
+ public static final Item PRISMARINE_STAIRS = register(new BlockItem(builder(), Blocks.PRISMARINE_STAIRS));
+ public static final Item PRISMARINE_BRICK_STAIRS = register(new BlockItem(builder(), Blocks.PRISMARINE_BRICK_STAIRS));
+ public static final Item DARK_PRISMARINE_STAIRS = register(new BlockItem(builder(), Blocks.DARK_PRISMARINE_STAIRS));
+ public static final Item SEA_LANTERN = register(new BlockItem(builder(), Blocks.SEA_LANTERN));
+ public static final Item RED_SANDSTONE = register(new BlockItem(builder(), Blocks.RED_SANDSTONE));
+ public static final Item CHISELED_RED_SANDSTONE = register(new BlockItem(builder(), Blocks.CHISELED_RED_SANDSTONE));
+ public static final Item CUT_RED_SANDSTONE = register(new BlockItem(builder(), Blocks.CUT_RED_SANDSTONE));
+ public static final Item RED_SANDSTONE_STAIRS = register(new BlockItem(builder(), Blocks.RED_SANDSTONE_STAIRS));
+ public static final Item REPEATING_COMMAND_BLOCK = register(new BlockItem(builder(), Blocks.REPEATING_COMMAND_BLOCK));
+ public static final Item CHAIN_COMMAND_BLOCK = register(new BlockItem(builder(), Blocks.CHAIN_COMMAND_BLOCK));
+ public static final Item MAGMA_BLOCK = register(new BlockItem(builder(), Blocks.MAGMA_BLOCK));
+ public static final Item NETHER_WART_BLOCK = register(new BlockItem(builder(), Blocks.NETHER_WART_BLOCK));
+ public static final Item WARPED_WART_BLOCK = register(new BlockItem(builder(), Blocks.WARPED_WART_BLOCK));
+ public static final Item RED_NETHER_BRICKS = register(new BlockItem(builder(), Blocks.RED_NETHER_BRICKS));
+ public static final Item BONE_BLOCK = register(new BlockItem(builder(), Blocks.BONE_BLOCK));
+ public static final Item STRUCTURE_VOID = register(new BlockItem(builder(), Blocks.STRUCTURE_VOID));
+ public static final Item SHULKER_BOX = register(new ShulkerBoxItem(builder().stackSize(1), Blocks.SHULKER_BOX));
+ public static final Item WHITE_SHULKER_BOX = register(new ShulkerBoxItem(builder().stackSize(1), Blocks.WHITE_SHULKER_BOX));
+ public static final Item ORANGE_SHULKER_BOX = register(new ShulkerBoxItem(builder().stackSize(1), Blocks.ORANGE_SHULKER_BOX));
+ public static final Item MAGENTA_SHULKER_BOX = register(new ShulkerBoxItem(builder().stackSize(1), Blocks.MAGENTA_SHULKER_BOX));
+ public static final Item LIGHT_BLUE_SHULKER_BOX = register(new ShulkerBoxItem(builder().stackSize(1), Blocks.LIGHT_BLUE_SHULKER_BOX));
+ public static final Item YELLOW_SHULKER_BOX = register(new ShulkerBoxItem(builder().stackSize(1), Blocks.YELLOW_SHULKER_BOX));
+ public static final Item LIME_SHULKER_BOX = register(new ShulkerBoxItem(builder().stackSize(1), Blocks.LIME_SHULKER_BOX));
+ public static final Item PINK_SHULKER_BOX = register(new ShulkerBoxItem(builder().stackSize(1), Blocks.PINK_SHULKER_BOX));
+ public static final Item GRAY_SHULKER_BOX = register(new ShulkerBoxItem(builder().stackSize(1), Blocks.GRAY_SHULKER_BOX));
+ public static final Item LIGHT_GRAY_SHULKER_BOX = register(new ShulkerBoxItem(builder().stackSize(1), Blocks.LIGHT_GRAY_SHULKER_BOX));
+ public static final Item CYAN_SHULKER_BOX = register(new ShulkerBoxItem(builder().stackSize(1), Blocks.CYAN_SHULKER_BOX));
+ public static final Item PURPLE_SHULKER_BOX = register(new ShulkerBoxItem(builder().stackSize(1), Blocks.PURPLE_SHULKER_BOX));
+ public static final Item BLUE_SHULKER_BOX = register(new ShulkerBoxItem(builder().stackSize(1), Blocks.BLUE_SHULKER_BOX));
+ public static final Item BROWN_SHULKER_BOX = register(new ShulkerBoxItem(builder().stackSize(1), Blocks.BROWN_SHULKER_BOX));
+ public static final Item GREEN_SHULKER_BOX = register(new ShulkerBoxItem(builder().stackSize(1), Blocks.GREEN_SHULKER_BOX));
+ public static final Item RED_SHULKER_BOX = register(new ShulkerBoxItem(builder().stackSize(1), Blocks.RED_SHULKER_BOX));
+ public static final Item BLACK_SHULKER_BOX = register(new ShulkerBoxItem(builder().stackSize(1), Blocks.BLACK_SHULKER_BOX));
+ public static final Item WHITE_GLAZED_TERRACOTTA = register(new BlockItem(builder(), Blocks.WHITE_GLAZED_TERRACOTTA));
+ public static final Item ORANGE_GLAZED_TERRACOTTA = register(new BlockItem(builder(), Blocks.ORANGE_GLAZED_TERRACOTTA));
+ public static final Item MAGENTA_GLAZED_TERRACOTTA = register(new BlockItem(builder(), Blocks.MAGENTA_GLAZED_TERRACOTTA));
+ public static final Item LIGHT_BLUE_GLAZED_TERRACOTTA = register(new BlockItem(builder(), Blocks.LIGHT_BLUE_GLAZED_TERRACOTTA));
+ public static final Item YELLOW_GLAZED_TERRACOTTA = register(new BlockItem(builder(), Blocks.YELLOW_GLAZED_TERRACOTTA));
+ public static final Item LIME_GLAZED_TERRACOTTA = register(new BlockItem(builder(), Blocks.LIME_GLAZED_TERRACOTTA));
+ public static final Item PINK_GLAZED_TERRACOTTA = register(new BlockItem(builder(), Blocks.PINK_GLAZED_TERRACOTTA));
+ public static final Item GRAY_GLAZED_TERRACOTTA = register(new BlockItem(builder(), Blocks.GRAY_GLAZED_TERRACOTTA));
+ public static final Item LIGHT_GRAY_GLAZED_TERRACOTTA = register(new BlockItem(builder(), Blocks.LIGHT_GRAY_GLAZED_TERRACOTTA));
+ public static final Item CYAN_GLAZED_TERRACOTTA = register(new BlockItem(builder(), Blocks.CYAN_GLAZED_TERRACOTTA));
+ public static final Item PURPLE_GLAZED_TERRACOTTA = register(new BlockItem(builder(), Blocks.PURPLE_GLAZED_TERRACOTTA));
+ public static final Item BLUE_GLAZED_TERRACOTTA = register(new BlockItem(builder(), Blocks.BLUE_GLAZED_TERRACOTTA));
+ public static final Item BROWN_GLAZED_TERRACOTTA = register(new BlockItem(builder(), Blocks.BROWN_GLAZED_TERRACOTTA));
+ public static final Item GREEN_GLAZED_TERRACOTTA = register(new BlockItem(builder(), Blocks.GREEN_GLAZED_TERRACOTTA));
+ public static final Item RED_GLAZED_TERRACOTTA = register(new BlockItem(builder(), Blocks.RED_GLAZED_TERRACOTTA));
+ public static final Item BLACK_GLAZED_TERRACOTTA = register(new BlockItem(builder(), Blocks.BLACK_GLAZED_TERRACOTTA));
+ public static final Item WHITE_CONCRETE = register(new BlockItem(builder(), Blocks.WHITE_CONCRETE));
+ public static final Item ORANGE_CONCRETE = register(new BlockItem(builder(), Blocks.ORANGE_CONCRETE));
+ public static final Item MAGENTA_CONCRETE = register(new BlockItem(builder(), Blocks.MAGENTA_CONCRETE));
+ public static final Item LIGHT_BLUE_CONCRETE = register(new BlockItem(builder(), Blocks.LIGHT_BLUE_CONCRETE));
+ public static final Item YELLOW_CONCRETE = register(new BlockItem(builder(), Blocks.YELLOW_CONCRETE));
+ public static final Item LIME_CONCRETE = register(new BlockItem(builder(), Blocks.LIME_CONCRETE));
+ public static final Item PINK_CONCRETE = register(new BlockItem(builder(), Blocks.PINK_CONCRETE));
+ public static final Item GRAY_CONCRETE = register(new BlockItem(builder(), Blocks.GRAY_CONCRETE));
+ public static final Item LIGHT_GRAY_CONCRETE = register(new BlockItem(builder(), Blocks.LIGHT_GRAY_CONCRETE));
+ public static final Item CYAN_CONCRETE = register(new BlockItem(builder(), Blocks.CYAN_CONCRETE));
+ public static final Item PURPLE_CONCRETE = register(new BlockItem(builder(), Blocks.PURPLE_CONCRETE));
+ public static final Item BLUE_CONCRETE = register(new BlockItem(builder(), Blocks.BLUE_CONCRETE));
+ public static final Item BROWN_CONCRETE = register(new BlockItem(builder(), Blocks.BROWN_CONCRETE));
+ public static final Item GREEN_CONCRETE = register(new BlockItem(builder(), Blocks.GREEN_CONCRETE));
+ public static final Item RED_CONCRETE = register(new BlockItem(builder(), Blocks.RED_CONCRETE));
+ public static final Item BLACK_CONCRETE = register(new BlockItem(builder(), Blocks.BLACK_CONCRETE));
+ public static final Item WHITE_CONCRETE_POWDER = register(new BlockItem(builder(), Blocks.WHITE_CONCRETE_POWDER));
+ public static final Item ORANGE_CONCRETE_POWDER = register(new BlockItem(builder(), Blocks.ORANGE_CONCRETE_POWDER));
+ public static final Item MAGENTA_CONCRETE_POWDER = register(new BlockItem(builder(), Blocks.MAGENTA_CONCRETE_POWDER));
+ public static final Item LIGHT_BLUE_CONCRETE_POWDER = register(new BlockItem(builder(), Blocks.LIGHT_BLUE_CONCRETE_POWDER));
+ public static final Item YELLOW_CONCRETE_POWDER = register(new BlockItem(builder(), Blocks.YELLOW_CONCRETE_POWDER));
+ public static final Item LIME_CONCRETE_POWDER = register(new BlockItem(builder(), Blocks.LIME_CONCRETE_POWDER));
+ public static final Item PINK_CONCRETE_POWDER = register(new BlockItem(builder(), Blocks.PINK_CONCRETE_POWDER));
+ public static final Item GRAY_CONCRETE_POWDER = register(new BlockItem(builder(), Blocks.GRAY_CONCRETE_POWDER));
+ public static final Item LIGHT_GRAY_CONCRETE_POWDER = register(new BlockItem(builder(), Blocks.LIGHT_GRAY_CONCRETE_POWDER));
+ public static final Item CYAN_CONCRETE_POWDER = register(new BlockItem(builder(), Blocks.CYAN_CONCRETE_POWDER));
+ public static final Item PURPLE_CONCRETE_POWDER = register(new BlockItem(builder(), Blocks.PURPLE_CONCRETE_POWDER));
+ public static final Item BLUE_CONCRETE_POWDER = register(new BlockItem(builder(), Blocks.BLUE_CONCRETE_POWDER));
+ public static final Item BROWN_CONCRETE_POWDER = register(new BlockItem(builder(), Blocks.BROWN_CONCRETE_POWDER));
+ public static final Item GREEN_CONCRETE_POWDER = register(new BlockItem(builder(), Blocks.GREEN_CONCRETE_POWDER));
+ public static final Item RED_CONCRETE_POWDER = register(new BlockItem(builder(), Blocks.RED_CONCRETE_POWDER));
+ public static final Item BLACK_CONCRETE_POWDER = register(new BlockItem(builder(), Blocks.BLACK_CONCRETE_POWDER));
+ public static final Item TURTLE_EGG = register(new BlockItem(builder(), Blocks.TURTLE_EGG));
+ public static final Item SNIFFER_EGG = register(new BlockItem(builder(), Blocks.SNIFFER_EGG));
+ public static final Item DEAD_TUBE_CORAL_BLOCK = register(new BlockItem(builder(), Blocks.DEAD_TUBE_CORAL_BLOCK));
+ public static final Item DEAD_BRAIN_CORAL_BLOCK = register(new BlockItem(builder(), Blocks.DEAD_BRAIN_CORAL_BLOCK));
+ public static final Item DEAD_BUBBLE_CORAL_BLOCK = register(new BlockItem(builder(), Blocks.DEAD_BUBBLE_CORAL_BLOCK));
+ public static final Item DEAD_FIRE_CORAL_BLOCK = register(new BlockItem(builder(), Blocks.DEAD_FIRE_CORAL_BLOCK));
+ public static final Item DEAD_HORN_CORAL_BLOCK = register(new BlockItem(builder(), Blocks.DEAD_HORN_CORAL_BLOCK));
+ public static final Item TUBE_CORAL_BLOCK = register(new BlockItem(builder(), Blocks.TUBE_CORAL_BLOCK));
+ public static final Item BRAIN_CORAL_BLOCK = register(new BlockItem(builder(), Blocks.BRAIN_CORAL_BLOCK));
+ public static final Item BUBBLE_CORAL_BLOCK = register(new BlockItem(builder(), Blocks.BUBBLE_CORAL_BLOCK));
+ public static final Item FIRE_CORAL_BLOCK = register(new BlockItem(builder(), Blocks.FIRE_CORAL_BLOCK));
+ public static final Item HORN_CORAL_BLOCK = register(new BlockItem(builder(), Blocks.HORN_CORAL_BLOCK));
+ public static final Item TUBE_CORAL = register(new BlockItem(builder(), Blocks.TUBE_CORAL));
+ public static final Item BRAIN_CORAL = register(new BlockItem(builder(), Blocks.BRAIN_CORAL));
+ public static final Item BUBBLE_CORAL = register(new BlockItem(builder(), Blocks.BUBBLE_CORAL));
+ public static final Item FIRE_CORAL = register(new BlockItem(builder(), Blocks.FIRE_CORAL));
+ public static final Item HORN_CORAL = register(new BlockItem(builder(), Blocks.HORN_CORAL));
+ public static final Item DEAD_BRAIN_CORAL = register(new BlockItem(builder(), Blocks.DEAD_BRAIN_CORAL));
+ public static final Item DEAD_BUBBLE_CORAL = register(new BlockItem(builder(), Blocks.DEAD_BUBBLE_CORAL));
+ public static final Item DEAD_FIRE_CORAL = register(new BlockItem(builder(), Blocks.DEAD_FIRE_CORAL));
+ public static final Item DEAD_HORN_CORAL = register(new BlockItem(builder(), Blocks.DEAD_HORN_CORAL));
+ public static final Item DEAD_TUBE_CORAL = register(new BlockItem(builder(), Blocks.DEAD_TUBE_CORAL));
+ public static final Item TUBE_CORAL_FAN = register(new BlockItem(builder(), Blocks.TUBE_CORAL_FAN, Blocks.TUBE_CORAL_WALL_FAN));
+ public static final Item BRAIN_CORAL_FAN = register(new BlockItem(builder(), Blocks.BRAIN_CORAL_FAN, Blocks.BRAIN_CORAL_WALL_FAN));
+ public static final Item BUBBLE_CORAL_FAN = register(new BlockItem(builder(), Blocks.BUBBLE_CORAL_FAN, Blocks.BUBBLE_CORAL_WALL_FAN));
+ public static final Item FIRE_CORAL_FAN = register(new BlockItem(builder(), Blocks.FIRE_CORAL_FAN, Blocks.FIRE_CORAL_WALL_FAN));
+ public static final Item HORN_CORAL_FAN = register(new BlockItem(builder(), Blocks.HORN_CORAL_FAN, Blocks.HORN_CORAL_WALL_FAN));
+ public static final Item DEAD_TUBE_CORAL_FAN = register(new BlockItem(builder(), Blocks.DEAD_TUBE_CORAL_FAN, Blocks.DEAD_TUBE_CORAL_WALL_FAN));
+ public static final Item DEAD_BRAIN_CORAL_FAN = register(new BlockItem(builder(), Blocks.DEAD_BRAIN_CORAL_FAN, Blocks.DEAD_BRAIN_CORAL_WALL_FAN));
+ public static final Item DEAD_BUBBLE_CORAL_FAN = register(new BlockItem(builder(), Blocks.DEAD_BUBBLE_CORAL_FAN, Blocks.DEAD_BUBBLE_CORAL_WALL_FAN));
+ public static final Item DEAD_FIRE_CORAL_FAN = register(new BlockItem(builder(), Blocks.DEAD_FIRE_CORAL_FAN, Blocks.DEAD_FIRE_CORAL_WALL_FAN));
+ public static final Item DEAD_HORN_CORAL_FAN = register(new BlockItem(builder(), Blocks.DEAD_HORN_CORAL_FAN, Blocks.DEAD_HORN_CORAL_WALL_FAN));
+ public static final Item BLUE_ICE = register(new BlockItem(builder(), Blocks.BLUE_ICE));
+ public static final Item CONDUIT = register(new BlockItem(builder(), Blocks.CONDUIT));
+ public static final Item POLISHED_GRANITE_STAIRS = register(new BlockItem(builder(), Blocks.POLISHED_GRANITE_STAIRS));
+ public static final Item SMOOTH_RED_SANDSTONE_STAIRS = register(new BlockItem(builder(), Blocks.SMOOTH_RED_SANDSTONE_STAIRS));
+ public static final Item MOSSY_STONE_BRICK_STAIRS = register(new BlockItem(builder(), Blocks.MOSSY_STONE_BRICK_STAIRS));
+ public static final Item POLISHED_DIORITE_STAIRS = register(new BlockItem(builder(), Blocks.POLISHED_DIORITE_STAIRS));
+ public static final Item MOSSY_COBBLESTONE_STAIRS = register(new BlockItem(builder(), Blocks.MOSSY_COBBLESTONE_STAIRS));
+ public static final Item END_STONE_BRICK_STAIRS = register(new BlockItem(builder(), Blocks.END_STONE_BRICK_STAIRS));
+ public static final Item STONE_STAIRS = register(new BlockItem(builder(), Blocks.STONE_STAIRS));
+ public static final Item SMOOTH_SANDSTONE_STAIRS = register(new BlockItem(builder(), Blocks.SMOOTH_SANDSTONE_STAIRS));
+ public static final Item SMOOTH_QUARTZ_STAIRS = register(new BlockItem(builder(), Blocks.SMOOTH_QUARTZ_STAIRS));
+ public static final Item GRANITE_STAIRS = register(new BlockItem(builder(), Blocks.GRANITE_STAIRS));
+ public static final Item ANDESITE_STAIRS = register(new BlockItem(builder(), Blocks.ANDESITE_STAIRS));
+ public static final Item RED_NETHER_BRICK_STAIRS = register(new BlockItem(builder(), Blocks.RED_NETHER_BRICK_STAIRS));
+ public static final Item POLISHED_ANDESITE_STAIRS = register(new BlockItem(builder(), Blocks.POLISHED_ANDESITE_STAIRS));
+ public static final Item DIORITE_STAIRS = register(new BlockItem(builder(), Blocks.DIORITE_STAIRS));
+ public static final Item COBBLED_DEEPSLATE_STAIRS = register(new BlockItem(builder(), Blocks.COBBLED_DEEPSLATE_STAIRS));
+ public static final Item POLISHED_DEEPSLATE_STAIRS = register(new BlockItem(builder(), Blocks.POLISHED_DEEPSLATE_STAIRS));
+ public static final Item DEEPSLATE_BRICK_STAIRS = register(new BlockItem(builder(), Blocks.DEEPSLATE_BRICK_STAIRS));
+ public static final Item DEEPSLATE_TILE_STAIRS = register(new BlockItem(builder(), Blocks.DEEPSLATE_TILE_STAIRS));
+ public static final Item POLISHED_GRANITE_SLAB = register(new BlockItem(builder(), Blocks.POLISHED_GRANITE_SLAB));
+ public static final Item SMOOTH_RED_SANDSTONE_SLAB = register(new BlockItem(builder(), Blocks.SMOOTH_RED_SANDSTONE_SLAB));
+ public static final Item MOSSY_STONE_BRICK_SLAB = register(new BlockItem(builder(), Blocks.MOSSY_STONE_BRICK_SLAB));
+ public static final Item POLISHED_DIORITE_SLAB = register(new BlockItem(builder(), Blocks.POLISHED_DIORITE_SLAB));
+ public static final Item MOSSY_COBBLESTONE_SLAB = register(new BlockItem(builder(), Blocks.MOSSY_COBBLESTONE_SLAB));
+ public static final Item END_STONE_BRICK_SLAB = register(new BlockItem(builder(), Blocks.END_STONE_BRICK_SLAB));
+ public static final Item SMOOTH_SANDSTONE_SLAB = register(new BlockItem(builder(), Blocks.SMOOTH_SANDSTONE_SLAB));
+ public static final Item SMOOTH_QUARTZ_SLAB = register(new BlockItem(builder(), Blocks.SMOOTH_QUARTZ_SLAB));
+ public static final Item GRANITE_SLAB = register(new BlockItem(builder(), Blocks.GRANITE_SLAB));
+ public static final Item ANDESITE_SLAB = register(new BlockItem(builder(), Blocks.ANDESITE_SLAB));
+ public static final Item RED_NETHER_BRICK_SLAB = register(new BlockItem(builder(), Blocks.RED_NETHER_BRICK_SLAB));
+ public static final Item POLISHED_ANDESITE_SLAB = register(new BlockItem(builder(), Blocks.POLISHED_ANDESITE_SLAB));
+ public static final Item DIORITE_SLAB = register(new BlockItem(builder(), Blocks.DIORITE_SLAB));
+ public static final Item COBBLED_DEEPSLATE_SLAB = register(new BlockItem(builder(), Blocks.COBBLED_DEEPSLATE_SLAB));
+ public static final Item POLISHED_DEEPSLATE_SLAB = register(new BlockItem(builder(), Blocks.POLISHED_DEEPSLATE_SLAB));
+ public static final Item DEEPSLATE_BRICK_SLAB = register(new BlockItem(builder(), Blocks.DEEPSLATE_BRICK_SLAB));
+ public static final Item DEEPSLATE_TILE_SLAB = register(new BlockItem(builder(), Blocks.DEEPSLATE_TILE_SLAB));
+ public static final Item SCAFFOLDING = register(new BlockItem(builder(), Blocks.SCAFFOLDING));
+ public static final Item REDSTONE = register(new BlockItem("redstone", builder(), Blocks.REDSTONE_WIRE));
+ public static final Item REDSTONE_TORCH = register(new BlockItem(builder(), Blocks.REDSTONE_TORCH, Blocks.REDSTONE_WALL_TORCH));
+ public static final Item REDSTONE_BLOCK = register(new BlockItem(builder(), Blocks.REDSTONE_BLOCK));
+ public static final Item REPEATER = register(new BlockItem(builder(), Blocks.REPEATER));
+ public static final Item COMPARATOR = register(new BlockItem(builder(), Blocks.COMPARATOR));
+ public static final Item PISTON = register(new BlockItem(builder(), Blocks.PISTON));
+ public static final Item STICKY_PISTON = register(new BlockItem(builder(), Blocks.STICKY_PISTON));
+ public static final Item SLIME_BLOCK = register(new BlockItem(builder(), Blocks.SLIME_BLOCK));
+ public static final Item HONEY_BLOCK = register(new BlockItem(builder(), Blocks.HONEY_BLOCK));
+ public static final Item OBSERVER = register(new BlockItem(builder(), Blocks.OBSERVER));
+ public static final Item HOPPER = register(new BlockItem(builder(), Blocks.HOPPER));
+ public static final Item DISPENSER = register(new BlockItem(builder(), Blocks.DISPENSER));
+ public static final Item DROPPER = register(new BlockItem(builder(), Blocks.DROPPER));
+ public static final Item LECTERN = register(new BlockItem(builder(), Blocks.LECTERN));
+ public static final Item TARGET = register(new BlockItem(builder(), Blocks.TARGET));
+ public static final Item LEVER = register(new BlockItem(builder(), Blocks.LEVER));
+ public static final Item LIGHTNING_ROD = register(new BlockItem(builder(), Blocks.LIGHTNING_ROD));
+ public static final Item DAYLIGHT_DETECTOR = register(new BlockItem(builder(), Blocks.DAYLIGHT_DETECTOR));
+ public static final Item SCULK_SENSOR = register(new BlockItem(builder(), Blocks.SCULK_SENSOR));
+ public static final Item CALIBRATED_SCULK_SENSOR = register(new BlockItem(builder(), Blocks.CALIBRATED_SCULK_SENSOR));
+ public static final Item TRIPWIRE_HOOK = register(new BlockItem(builder(), Blocks.TRIPWIRE_HOOK));
+ public static final Item TRAPPED_CHEST = register(new BlockItem(builder(), Blocks.TRAPPED_CHEST));
+ public static final Item TNT = register(new BlockItem(builder(), Blocks.TNT));
+ public static final Item REDSTONE_LAMP = register(new BlockItem(builder(), Blocks.REDSTONE_LAMP));
+ public static final Item NOTE_BLOCK = register(new BlockItem(builder(), Blocks.NOTE_BLOCK));
+ public static final Item STONE_BUTTON = register(new BlockItem(builder(), Blocks.STONE_BUTTON));
+ public static final Item POLISHED_BLACKSTONE_BUTTON = register(new BlockItem(builder(), Blocks.POLISHED_BLACKSTONE_BUTTON));
+ public static final Item OAK_BUTTON = register(new BlockItem(builder(), Blocks.OAK_BUTTON));
+ public static final Item SPRUCE_BUTTON = register(new BlockItem(builder(), Blocks.SPRUCE_BUTTON));
+ public static final Item BIRCH_BUTTON = register(new BlockItem(builder(), Blocks.BIRCH_BUTTON));
+ public static final Item JUNGLE_BUTTON = register(new BlockItem(builder(), Blocks.JUNGLE_BUTTON));
+ public static final Item ACACIA_BUTTON = register(new BlockItem(builder(), Blocks.ACACIA_BUTTON));
+ public static final Item CHERRY_BUTTON = register(new BlockItem(builder(), Blocks.CHERRY_BUTTON));
+ public static final Item DARK_OAK_BUTTON = register(new BlockItem(builder(), Blocks.DARK_OAK_BUTTON));
+ public static final Item MANGROVE_BUTTON = register(new BlockItem(builder(), Blocks.MANGROVE_BUTTON));
+ public static final Item BAMBOO_BUTTON = register(new BlockItem(builder(), Blocks.BAMBOO_BUTTON));
+ public static final Item CRIMSON_BUTTON = register(new BlockItem(builder(), Blocks.CRIMSON_BUTTON));
+ public static final Item WARPED_BUTTON = register(new BlockItem(builder(), Blocks.WARPED_BUTTON));
+ public static final Item STONE_PRESSURE_PLATE = register(new BlockItem(builder(), Blocks.STONE_PRESSURE_PLATE));
+ public static final Item POLISHED_BLACKSTONE_PRESSURE_PLATE = register(new BlockItem(builder(), Blocks.POLISHED_BLACKSTONE_PRESSURE_PLATE));
+ public static final Item LIGHT_WEIGHTED_PRESSURE_PLATE = register(new BlockItem(builder(), Blocks.LIGHT_WEIGHTED_PRESSURE_PLATE));
+ public static final Item HEAVY_WEIGHTED_PRESSURE_PLATE = register(new BlockItem(builder(), Blocks.HEAVY_WEIGHTED_PRESSURE_PLATE));
+ public static final Item OAK_PRESSURE_PLATE = register(new BlockItem(builder(), Blocks.OAK_PRESSURE_PLATE));
+ public static final Item SPRUCE_PRESSURE_PLATE = register(new BlockItem(builder(), Blocks.SPRUCE_PRESSURE_PLATE));
+ public static final Item BIRCH_PRESSURE_PLATE = register(new BlockItem(builder(), Blocks.BIRCH_PRESSURE_PLATE));
+ public static final Item JUNGLE_PRESSURE_PLATE = register(new BlockItem(builder(), Blocks.JUNGLE_PRESSURE_PLATE));
+ public static final Item ACACIA_PRESSURE_PLATE = register(new BlockItem(builder(), Blocks.ACACIA_PRESSURE_PLATE));
+ public static final Item CHERRY_PRESSURE_PLATE = register(new BlockItem(builder(), Blocks.CHERRY_PRESSURE_PLATE));
+ public static final Item DARK_OAK_PRESSURE_PLATE = register(new BlockItem(builder(), Blocks.DARK_OAK_PRESSURE_PLATE));
+ public static final Item MANGROVE_PRESSURE_PLATE = register(new BlockItem(builder(), Blocks.MANGROVE_PRESSURE_PLATE));
+ public static final Item BAMBOO_PRESSURE_PLATE = register(new BlockItem(builder(), Blocks.BAMBOO_PRESSURE_PLATE));
+ public static final Item CRIMSON_PRESSURE_PLATE = register(new BlockItem(builder(), Blocks.CRIMSON_PRESSURE_PLATE));
+ public static final Item WARPED_PRESSURE_PLATE = register(new BlockItem(builder(), Blocks.WARPED_PRESSURE_PLATE));
+ public static final Item IRON_DOOR = register(new BlockItem(builder(), Blocks.IRON_DOOR));
+ public static final Item OAK_DOOR = register(new BlockItem(builder(), Blocks.OAK_DOOR));
+ public static final Item SPRUCE_DOOR = register(new BlockItem(builder(), Blocks.SPRUCE_DOOR));
+ public static final Item BIRCH_DOOR = register(new BlockItem(builder(), Blocks.BIRCH_DOOR));
+ public static final Item JUNGLE_DOOR = register(new BlockItem(builder(), Blocks.JUNGLE_DOOR));
+ public static final Item ACACIA_DOOR = register(new BlockItem(builder(), Blocks.ACACIA_DOOR));
+ public static final Item CHERRY_DOOR = register(new BlockItem(builder(), Blocks.CHERRY_DOOR));
+ public static final Item DARK_OAK_DOOR = register(new BlockItem(builder(), Blocks.DARK_OAK_DOOR));
+ public static final Item MANGROVE_DOOR = register(new BlockItem(builder(), Blocks.MANGROVE_DOOR));
+ public static final Item BAMBOO_DOOR = register(new BlockItem(builder(), Blocks.BAMBOO_DOOR));
+ public static final Item CRIMSON_DOOR = register(new BlockItem(builder(), Blocks.CRIMSON_DOOR));
+ public static final Item WARPED_DOOR = register(new BlockItem(builder(), Blocks.WARPED_DOOR));
+ public static final Item COPPER_DOOR = register(new BlockItem(builder(), Blocks.COPPER_DOOR));
+ public static final Item EXPOSED_COPPER_DOOR = register(new BlockItem(builder(), Blocks.EXPOSED_COPPER_DOOR));
+ public static final Item WEATHERED_COPPER_DOOR = register(new BlockItem(builder(), Blocks.WEATHERED_COPPER_DOOR));
+ public static final Item OXIDIZED_COPPER_DOOR = register(new BlockItem(builder(), Blocks.OXIDIZED_COPPER_DOOR));
+ public static final Item WAXED_COPPER_DOOR = register(new BlockItem(builder(), Blocks.WAXED_COPPER_DOOR));
+ public static final Item WAXED_EXPOSED_COPPER_DOOR = register(new BlockItem(builder(), Blocks.WAXED_EXPOSED_COPPER_DOOR));
+ public static final Item WAXED_WEATHERED_COPPER_DOOR = register(new BlockItem(builder(), Blocks.WAXED_WEATHERED_COPPER_DOOR));
+ public static final Item WAXED_OXIDIZED_COPPER_DOOR = register(new BlockItem(builder(), Blocks.WAXED_OXIDIZED_COPPER_DOOR));
+ public static final Item IRON_TRAPDOOR = register(new BlockItem(builder(), Blocks.IRON_TRAPDOOR));
+ public static final Item OAK_TRAPDOOR = register(new BlockItem(builder(), Blocks.OAK_TRAPDOOR));
+ public static final Item SPRUCE_TRAPDOOR = register(new BlockItem(builder(), Blocks.SPRUCE_TRAPDOOR));
+ public static final Item BIRCH_TRAPDOOR = register(new BlockItem(builder(), Blocks.BIRCH_TRAPDOOR));
+ public static final Item JUNGLE_TRAPDOOR = register(new BlockItem(builder(), Blocks.JUNGLE_TRAPDOOR));
+ public static final Item ACACIA_TRAPDOOR = register(new BlockItem(builder(), Blocks.ACACIA_TRAPDOOR));
+ public static final Item CHERRY_TRAPDOOR = register(new BlockItem(builder(), Blocks.CHERRY_TRAPDOOR));
+ public static final Item DARK_OAK_TRAPDOOR = register(new BlockItem(builder(), Blocks.DARK_OAK_TRAPDOOR));
+ public static final Item MANGROVE_TRAPDOOR = register(new BlockItem(builder(), Blocks.MANGROVE_TRAPDOOR));
+ public static final Item BAMBOO_TRAPDOOR = register(new BlockItem(builder(), Blocks.BAMBOO_TRAPDOOR));
+ public static final Item CRIMSON_TRAPDOOR = register(new BlockItem(builder(), Blocks.CRIMSON_TRAPDOOR));
+ public static final Item WARPED_TRAPDOOR = register(new BlockItem(builder(), Blocks.WARPED_TRAPDOOR));
+ public static final Item COPPER_TRAPDOOR = register(new BlockItem(builder(), Blocks.COPPER_TRAPDOOR));
+ public static final Item EXPOSED_COPPER_TRAPDOOR = register(new BlockItem(builder(), Blocks.EXPOSED_COPPER_TRAPDOOR));
+ public static final Item WEATHERED_COPPER_TRAPDOOR = register(new BlockItem(builder(), Blocks.WEATHERED_COPPER_TRAPDOOR));
+ public static final Item OXIDIZED_COPPER_TRAPDOOR = register(new BlockItem(builder(), Blocks.OXIDIZED_COPPER_TRAPDOOR));
+ public static final Item WAXED_COPPER_TRAPDOOR = register(new BlockItem(builder(), Blocks.WAXED_COPPER_TRAPDOOR));
+ public static final Item WAXED_EXPOSED_COPPER_TRAPDOOR = register(new BlockItem(builder(), Blocks.WAXED_EXPOSED_COPPER_TRAPDOOR));
+ public static final Item WAXED_WEATHERED_COPPER_TRAPDOOR = register(new BlockItem(builder(), Blocks.WAXED_WEATHERED_COPPER_TRAPDOOR));
+ public static final Item WAXED_OXIDIZED_COPPER_TRAPDOOR = register(new BlockItem(builder(), Blocks.WAXED_OXIDIZED_COPPER_TRAPDOOR));
+ public static final Item OAK_FENCE_GATE = register(new BlockItem(builder(), Blocks.OAK_FENCE_GATE));
+ public static final Item SPRUCE_FENCE_GATE = register(new BlockItem(builder(), Blocks.SPRUCE_FENCE_GATE));
+ public static final Item BIRCH_FENCE_GATE = register(new BlockItem(builder(), Blocks.BIRCH_FENCE_GATE));
+ public static final Item JUNGLE_FENCE_GATE = register(new BlockItem(builder(), Blocks.JUNGLE_FENCE_GATE));
+ public static final Item ACACIA_FENCE_GATE = register(new BlockItem(builder(), Blocks.ACACIA_FENCE_GATE));
+ public static final Item CHERRY_FENCE_GATE = register(new BlockItem(builder(), Blocks.CHERRY_FENCE_GATE));
+ public static final Item DARK_OAK_FENCE_GATE = register(new BlockItem(builder(), Blocks.DARK_OAK_FENCE_GATE));
+ public static final Item MANGROVE_FENCE_GATE = register(new BlockItem(builder(), Blocks.MANGROVE_FENCE_GATE));
+ public static final Item BAMBOO_FENCE_GATE = register(new BlockItem(builder(), Blocks.BAMBOO_FENCE_GATE));
+ public static final Item CRIMSON_FENCE_GATE = register(new BlockItem(builder(), Blocks.CRIMSON_FENCE_GATE));
+ public static final Item WARPED_FENCE_GATE = register(new BlockItem(builder(), Blocks.WARPED_FENCE_GATE));
+ public static final Item POWERED_RAIL = register(new BlockItem(builder(), Blocks.POWERED_RAIL));
+ public static final Item DETECTOR_RAIL = register(new BlockItem(builder(), Blocks.DETECTOR_RAIL));
+ public static final Item RAIL = register(new BlockItem(builder(), Blocks.RAIL));
+ public static final Item ACTIVATOR_RAIL = register(new BlockItem(builder(), Blocks.ACTIVATOR_RAIL));
public static final Item SADDLE = register(new Item("saddle", builder().stackSize(1)));
public static final Item MINECART = register(new Item("minecart", builder().stackSize(1)));
public static final Item CHEST_MINECART = register(new Item("chest_minecart", builder().stackSize(1)));
@@ -830,13 +829,14 @@ public final class Items {
public static final Item MANGROVE_CHEST_BOAT = register(new BoatItem("mangrove_chest_boat", builder().stackSize(1)));
public static final Item BAMBOO_RAFT = register(new BoatItem("bamboo_raft", builder().stackSize(1)));
public static final Item BAMBOO_CHEST_RAFT = register(new BoatItem("bamboo_chest_raft", builder().stackSize(1)));
- public static final Item STRUCTURE_BLOCK = register(new BlockItem("structure_block", builder()));
- public static final Item JIGSAW = register(new BlockItem("jigsaw", builder()));
+ public static final Item STRUCTURE_BLOCK = register(new BlockItem(builder(), Blocks.STRUCTURE_BLOCK));
+ public static final Item JIGSAW = register(new BlockItem(builder(), Blocks.JIGSAW));
public static final Item TURTLE_HELMET = register(new ArmorItem("turtle_helmet", ArmorMaterial.TURTLE, builder().stackSize(1).maxDamage(275)));
public static final Item TURTLE_SCUTE = register(new Item("turtle_scute", builder()));
public static final Item ARMADILLO_SCUTE = register(new Item("armadillo_scute", builder()));
- public static final Item WOLF_ARMOR = register(new ArmorItem("wolf_armor", ArmorMaterial.ARMADILLO, builder().stackSize(1).maxDamage(64)));
+ public static final Item WOLF_ARMOR = register(new WolfArmorItem("wolf_armor", ArmorMaterial.ARMADILLO, builder().stackSize(1).maxDamage(64)));
public static final Item FLINT_AND_STEEL = register(new Item("flint_and_steel", builder().stackSize(1).maxDamage(64)));
+ public static final Item BOWL = register(new Item("bowl", builder()));
public static final Item APPLE = register(new Item("apple", builder()));
public static final Item BOW = register(new Item("bow", builder().stackSize(1).maxDamage(384)));
public static final Item ARROW = register(new ArrowItem("arrow", builder()));
@@ -886,12 +886,11 @@ public final class Items {
public static final Item NETHERITE_AXE = register(new TieredItem("netherite_axe", ToolTier.NETHERITE, builder().stackSize(1).maxDamage(2031).attackDamage(10.0)));
public static final Item NETHERITE_HOE = register(new TieredItem("netherite_hoe", ToolTier.NETHERITE, builder().stackSize(1).maxDamage(2031).attackDamage(1.0)));
public static final Item STICK = register(new Item("stick", builder()));
- public static final Item BOWL = register(new Item("bowl", builder()));
public static final Item MUSHROOM_STEW = register(new Item("mushroom_stew", builder().stackSize(1)));
- public static final Item STRING = register(new BlockItem("string", builder()));
+ public static final Item STRING = register(new BlockItem("string", builder(), Blocks.TRIPWIRE));
public static final Item FEATHER = register(new Item("feather", builder()));
public static final Item GUNPOWDER = register(new Item("gunpowder", builder()));
- public static final Item WHEAT_SEEDS = register(new BlockItem("wheat_seeds", builder()));
+ public static final Item WHEAT_SEEDS = register(new BlockItem("wheat_seeds", builder(), Blocks.WHEAT));
public static final Item WHEAT = register(new Item("wheat", builder()));
public static final Item BREAD = register(new Item("bread", builder()));
public static final Item LEATHER_HELMET = register(new DyeableArmorItem("leather_helmet", ArmorMaterial.LEATHER, builder().stackSize(1).maxDamage(55)));
@@ -924,32 +923,32 @@ public final class Items {
public static final Item PAINTING = register(new Item("painting", builder()));
public static final Item GOLDEN_APPLE = register(new Item("golden_apple", builder()));
public static final Item ENCHANTED_GOLDEN_APPLE = register(new Item("enchanted_golden_apple", builder()));
- public static final Item OAK_SIGN = register(new BlockItem("oak_sign", builder().stackSize(16)));
- public static final Item SPRUCE_SIGN = register(new BlockItem("spruce_sign", builder().stackSize(16)));
- public static final Item BIRCH_SIGN = register(new BlockItem("birch_sign", builder().stackSize(16)));
- public static final Item JUNGLE_SIGN = register(new BlockItem("jungle_sign", builder().stackSize(16)));
- public static final Item ACACIA_SIGN = register(new BlockItem("acacia_sign", builder().stackSize(16)));
- public static final Item CHERRY_SIGN = register(new BlockItem("cherry_sign", builder().stackSize(16)));
- public static final Item DARK_OAK_SIGN = register(new BlockItem("dark_oak_sign", builder().stackSize(16)));
- public static final Item MANGROVE_SIGN = register(new BlockItem("mangrove_sign", builder().stackSize(16)));
- public static final Item BAMBOO_SIGN = register(new BlockItem("bamboo_sign", builder().stackSize(16)));
- public static final Item CRIMSON_SIGN = register(new BlockItem("crimson_sign", builder().stackSize(16)));
- public static final Item WARPED_SIGN = register(new BlockItem("warped_sign", builder().stackSize(16)));
- public static final Item OAK_HANGING_SIGN = register(new BlockItem("oak_hanging_sign", builder().stackSize(16)));
- public static final Item SPRUCE_HANGING_SIGN = register(new BlockItem("spruce_hanging_sign", builder().stackSize(16)));
- public static final Item BIRCH_HANGING_SIGN = register(new BlockItem("birch_hanging_sign", builder().stackSize(16)));
- public static final Item JUNGLE_HANGING_SIGN = register(new BlockItem("jungle_hanging_sign", builder().stackSize(16)));
- public static final Item ACACIA_HANGING_SIGN = register(new BlockItem("acacia_hanging_sign", builder().stackSize(16)));
- public static final Item CHERRY_HANGING_SIGN = register(new BlockItem("cherry_hanging_sign", builder().stackSize(16)));
- public static final Item DARK_OAK_HANGING_SIGN = register(new BlockItem("dark_oak_hanging_sign", builder().stackSize(16)));
- public static final Item MANGROVE_HANGING_SIGN = register(new BlockItem("mangrove_hanging_sign", builder().stackSize(16)));
- public static final Item BAMBOO_HANGING_SIGN = register(new BlockItem("bamboo_hanging_sign", builder().stackSize(16)));
- public static final Item CRIMSON_HANGING_SIGN = register(new BlockItem("crimson_hanging_sign", builder().stackSize(16)));
- public static final Item WARPED_HANGING_SIGN = register(new BlockItem("warped_hanging_sign", builder().stackSize(16)));
+ public static final Item OAK_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.OAK_SIGN, Blocks.OAK_WALL_SIGN));
+ public static final Item SPRUCE_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.SPRUCE_SIGN, Blocks.SPRUCE_WALL_SIGN));
+ public static final Item BIRCH_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.BIRCH_SIGN, Blocks.BIRCH_WALL_SIGN));
+ public static final Item JUNGLE_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.JUNGLE_SIGN, Blocks.JUNGLE_WALL_SIGN));
+ public static final Item ACACIA_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.ACACIA_SIGN, Blocks.ACACIA_WALL_SIGN));
+ public static final Item CHERRY_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.CHERRY_SIGN, Blocks.CHERRY_WALL_SIGN));
+ public static final Item DARK_OAK_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.DARK_OAK_SIGN, Blocks.DARK_OAK_WALL_SIGN));
+ public static final Item MANGROVE_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.MANGROVE_SIGN, Blocks.MANGROVE_WALL_SIGN));
+ public static final Item BAMBOO_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.BAMBOO_SIGN, Blocks.BAMBOO_WALL_SIGN));
+ public static final Item CRIMSON_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.CRIMSON_SIGN, Blocks.CRIMSON_WALL_SIGN));
+ public static final Item WARPED_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.WARPED_SIGN, Blocks.WARPED_WALL_SIGN));
+ public static final Item OAK_HANGING_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.OAK_HANGING_SIGN, Blocks.OAK_WALL_HANGING_SIGN));
+ public static final Item SPRUCE_HANGING_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.SPRUCE_HANGING_SIGN, Blocks.SPRUCE_WALL_HANGING_SIGN));
+ public static final Item BIRCH_HANGING_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.BIRCH_HANGING_SIGN, Blocks.BIRCH_WALL_HANGING_SIGN));
+ public static final Item JUNGLE_HANGING_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.JUNGLE_HANGING_SIGN, Blocks.JUNGLE_WALL_HANGING_SIGN));
+ public static final Item ACACIA_HANGING_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.ACACIA_HANGING_SIGN, Blocks.ACACIA_WALL_HANGING_SIGN));
+ public static final Item CHERRY_HANGING_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.CHERRY_HANGING_SIGN, Blocks.CHERRY_WALL_HANGING_SIGN));
+ public static final Item DARK_OAK_HANGING_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.DARK_OAK_HANGING_SIGN, Blocks.DARK_OAK_WALL_HANGING_SIGN));
+ public static final Item MANGROVE_HANGING_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.MANGROVE_HANGING_SIGN, Blocks.MANGROVE_WALL_HANGING_SIGN));
+ public static final Item BAMBOO_HANGING_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.BAMBOO_HANGING_SIGN, Blocks.BAMBOO_WALL_HANGING_SIGN));
+ public static final Item CRIMSON_HANGING_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.CRIMSON_HANGING_SIGN, Blocks.CRIMSON_WALL_HANGING_SIGN));
+ public static final Item WARPED_HANGING_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.WARPED_HANGING_SIGN, Blocks.WARPED_WALL_HANGING_SIGN));
public static final Item BUCKET = register(new Item("bucket", builder().stackSize(16)));
public static final Item WATER_BUCKET = register(new Item("water_bucket", builder().stackSize(1)));
public static final Item LAVA_BUCKET = register(new Item("lava_bucket", builder().stackSize(1)));
- public static final Item POWDER_SNOW_BUCKET = register(new BlockItem("powder_snow_bucket", builder().stackSize(1)));
+ public static final Item POWDER_SNOW_BUCKET = register(new BlockItem("powder_snow_bucket", builder().stackSize(1), Blocks.POWDER_SNOW));
public static final Item SNOWBALL = register(new Item("snowball", builder().stackSize(16)));
public static final Item LEATHER = register(new Item("leather", builder()));
public static final Item MILK_BUCKET = register(new Item("milk_bucket", builder().stackSize(1)));
@@ -961,7 +960,7 @@ public final class Items {
public static final Item TADPOLE_BUCKET = register(new Item("tadpole_bucket", builder().stackSize(1)));
public static final Item BRICK = register(new Item("brick", builder()));
public static final Item CLAY_BALL = register(new Item("clay_ball", builder()));
- public static final Item DRIED_KELP_BLOCK = register(new BlockItem("dried_kelp_block", builder()));
+ public static final Item DRIED_KELP_BLOCK = register(new BlockItem(builder(), Blocks.DRIED_KELP_BLOCK));
public static final Item PAPER = register(new Item("paper", builder()));
public static final Item BOOK = register(new Item("book", builder()));
public static final Item SLIME_BALL = register(new Item("slime_ball", builder()));
@@ -981,7 +980,7 @@ public final class Items {
public static final Item COOKED_SALMON = register(new Item("cooked_salmon", builder()));
public static final Item INK_SAC = register(new Item("ink_sac", builder()));
public static final Item GLOW_INK_SAC = register(new Item("glow_ink_sac", builder()));
- public static final Item COCOA_BEANS = register(new BlockItem("cocoa_beans", builder()));
+ public static final Item COCOA_BEANS = register(new BlockItem("cocoa_beans", builder(), Blocks.COCOA));
public static final Item WHITE_DYE = register(new DyeItem("white_dye", 0, builder()));
public static final Item ORANGE_DYE = register(new DyeItem("orange_dye", 1, builder()));
public static final Item MAGENTA_DYE = register(new DyeItem("magenta_dye", 2, builder()));
@@ -1001,31 +1000,31 @@ public final class Items {
public static final Item BONE_MEAL = register(new Item("bone_meal", builder()));
public static final Item BONE = register(new Item("bone", builder()));
public static final Item SUGAR = register(new Item("sugar", builder()));
- public static final Item CAKE = register(new BlockItem("cake", builder().stackSize(1)));
- public static final Item WHITE_BED = register(new BlockItem("white_bed", builder().stackSize(1)));
- public static final Item ORANGE_BED = register(new BlockItem("orange_bed", builder().stackSize(1)));
- public static final Item MAGENTA_BED = register(new BlockItem("magenta_bed", builder().stackSize(1)));
- public static final Item LIGHT_BLUE_BED = register(new BlockItem("light_blue_bed", builder().stackSize(1)));
- public static final Item YELLOW_BED = register(new BlockItem("yellow_bed", builder().stackSize(1)));
- public static final Item LIME_BED = register(new BlockItem("lime_bed", builder().stackSize(1)));
- public static final Item PINK_BED = register(new BlockItem("pink_bed", builder().stackSize(1)));
- public static final Item GRAY_BED = register(new BlockItem("gray_bed", builder().stackSize(1)));
- public static final Item LIGHT_GRAY_BED = register(new BlockItem("light_gray_bed", builder().stackSize(1)));
- public static final Item CYAN_BED = register(new BlockItem("cyan_bed", builder().stackSize(1)));
- public static final Item PURPLE_BED = register(new BlockItem("purple_bed", builder().stackSize(1)));
- public static final Item BLUE_BED = register(new BlockItem("blue_bed", builder().stackSize(1)));
- public static final Item BROWN_BED = register(new BlockItem("brown_bed", builder().stackSize(1)));
- public static final Item GREEN_BED = register(new BlockItem("green_bed", builder().stackSize(1)));
- public static final Item RED_BED = register(new BlockItem("red_bed", builder().stackSize(1)));
- public static final Item BLACK_BED = register(new BlockItem("black_bed", builder().stackSize(1)));
+ public static final Item CAKE = register(new BlockItem(builder().stackSize(1), Blocks.CAKE));
+ public static final Item WHITE_BED = register(new BlockItem(builder().stackSize(1), Blocks.WHITE_BED));
+ public static final Item ORANGE_BED = register(new BlockItem(builder().stackSize(1), Blocks.ORANGE_BED));
+ public static final Item MAGENTA_BED = register(new BlockItem(builder().stackSize(1), Blocks.MAGENTA_BED));
+ public static final Item LIGHT_BLUE_BED = register(new BlockItem(builder().stackSize(1), Blocks.LIGHT_BLUE_BED));
+ public static final Item YELLOW_BED = register(new BlockItem(builder().stackSize(1), Blocks.YELLOW_BED));
+ public static final Item LIME_BED = register(new BlockItem(builder().stackSize(1), Blocks.LIME_BED));
+ public static final Item PINK_BED = register(new BlockItem(builder().stackSize(1), Blocks.PINK_BED));
+ public static final Item GRAY_BED = register(new BlockItem(builder().stackSize(1), Blocks.GRAY_BED));
+ public static final Item LIGHT_GRAY_BED = register(new BlockItem(builder().stackSize(1), Blocks.LIGHT_GRAY_BED));
+ public static final Item CYAN_BED = register(new BlockItem(builder().stackSize(1), Blocks.CYAN_BED));
+ public static final Item PURPLE_BED = register(new BlockItem(builder().stackSize(1), Blocks.PURPLE_BED));
+ public static final Item BLUE_BED = register(new BlockItem(builder().stackSize(1), Blocks.BLUE_BED));
+ public static final Item BROWN_BED = register(new BlockItem(builder().stackSize(1), Blocks.BROWN_BED));
+ public static final Item GREEN_BED = register(new BlockItem(builder().stackSize(1), Blocks.GREEN_BED));
+ public static final Item RED_BED = register(new BlockItem(builder().stackSize(1), Blocks.RED_BED));
+ public static final Item BLACK_BED = register(new BlockItem(builder().stackSize(1), Blocks.BLACK_BED));
public static final Item COOKIE = register(new Item("cookie", builder()));
- public static final Item CRAFTER = register(new BlockItem("crafter", builder()));
+ public static final Item CRAFTER = register(new BlockItem(builder(), Blocks.CRAFTER));
public static final Item FILLED_MAP = register(new FilledMapItem("filled_map", builder()));
public static final Item SHEARS = register(new Item("shears", builder().stackSize(1).maxDamage(238)));
public static final Item MELON_SLICE = register(new Item("melon_slice", builder()));
public static final Item DRIED_KELP = register(new Item("dried_kelp", builder()));
- public static final Item PUMPKIN_SEEDS = register(new BlockItem("pumpkin_seeds", builder()));
- public static final Item MELON_SEEDS = register(new BlockItem("melon_seeds", builder()));
+ public static final Item PUMPKIN_SEEDS = register(new BlockItem("pumpkin_seeds", builder(), Blocks.PUMPKIN_STEM));
+ public static final Item MELON_SEEDS = register(new BlockItem("melon_seeds", builder(), Blocks.MELON_STEM));
public static final Item BEEF = register(new Item("beef", builder()));
public static final Item COOKED_BEEF = register(new Item("cooked_beef", builder()));
public static final Item CHICKEN = register(new Item("chicken", builder()));
@@ -1035,15 +1034,15 @@ public final class Items {
public static final Item BLAZE_ROD = register(new Item("blaze_rod", builder()));
public static final Item GHAST_TEAR = register(new Item("ghast_tear", builder()));
public static final Item GOLD_NUGGET = register(new Item("gold_nugget", builder()));
- public static final Item NETHER_WART = register(new BlockItem("nether_wart", builder()));
+ public static final Item NETHER_WART = register(new BlockItem(builder(), Blocks.NETHER_WART));
public static final Item POTION = register(new PotionItem("potion", builder().stackSize(1)));
public static final Item GLASS_BOTTLE = register(new Item("glass_bottle", builder()));
public static final Item SPIDER_EYE = register(new Item("spider_eye", builder()));
public static final Item FERMENTED_SPIDER_EYE = register(new Item("fermented_spider_eye", builder()));
public static final Item BLAZE_POWDER = register(new Item("blaze_powder", builder()));
public static final Item MAGMA_CREAM = register(new Item("magma_cream", builder()));
- public static final Item BREWING_STAND = register(new BlockItem("brewing_stand", builder()));
- public static final Item CAULDRON = register(new BlockItem("cauldron", builder()));
+ public static final Item BREWING_STAND = register(new BlockItem(builder(), Blocks.BREWING_STAND));
+ public static final Item CAULDRON = register(new BlockItem(builder(), Blocks.CAULDRON, Blocks.WATER_CAULDRON, Blocks.LAVA_CAULDRON, Blocks.POWDER_SNOW_CAULDRON));
public static final Item ENDER_EYE = register(new Item("ender_eye", builder()));
public static final Item GLISTERING_MELON_SLICE = register(new Item("glistering_melon_slice", builder()));
public static final Item ARMADILLO_SPAWN_EGG = register(new SpawnEggItem("armadillo_spawn_egg", builder()));
@@ -1131,23 +1130,23 @@ public final class Items {
public static final Item WIND_CHARGE = register(new Item("wind_charge", builder()));
public static final Item WRITABLE_BOOK = register(new WritableBookItem("writable_book", builder().stackSize(1)));
public static final Item WRITTEN_BOOK = register(new WrittenBookItem("written_book", builder().stackSize(16)));
- public static final Item MACE = register(new MaceItem("mace", builder().stackSize(1).maxDamage(250)));
+ public static final Item MACE = register(new MaceItem("mace", builder().stackSize(1).maxDamage(500)));
public static final Item ITEM_FRAME = register(new Item("item_frame", builder()));
public static final Item GLOW_ITEM_FRAME = register(new Item("glow_item_frame", builder()));
- public static final Item FLOWER_POT = register(new BlockItem("flower_pot", builder()));
- public static final Item CARROT = register(new BlockItem("carrot", builder()));
- public static final Item POTATO = register(new BlockItem("potato", builder()));
+ public static final Item FLOWER_POT = register(new BlockItem(builder(), Blocks.FLOWER_POT));
+ public static final Item CARROT = register(new BlockItem("carrot", builder(), Blocks.CARROTS));
+ public static final Item POTATO = register(new BlockItem("potato", builder(), Blocks.POTATOES));
public static final Item BAKED_POTATO = register(new Item("baked_potato", builder()));
public static final Item POISONOUS_POTATO = register(new Item("poisonous_potato", builder()));
public static final Item MAP = register(new MapItem("map", builder()));
public static final Item GOLDEN_CARROT = register(new Item("golden_carrot", builder()));
- public static final Item SKELETON_SKULL = register(new BlockItem("skeleton_skull", builder()));
- public static final Item WITHER_SKELETON_SKULL = register(new BlockItem("wither_skeleton_skull", builder()));
- public static final Item PLAYER_HEAD = register(new PlayerHeadItem("player_head", builder()));
- public static final Item ZOMBIE_HEAD = register(new BlockItem("zombie_head", builder()));
- public static final Item CREEPER_HEAD = register(new BlockItem("creeper_head", builder()));
- public static final Item DRAGON_HEAD = register(new BlockItem("dragon_head", builder()));
- public static final Item PIGLIN_HEAD = register(new BlockItem("piglin_head", builder()));
+ public static final Item SKELETON_SKULL = register(new BlockItem(builder(), Blocks.SKELETON_SKULL, Blocks.SKELETON_WALL_SKULL));
+ public static final Item WITHER_SKELETON_SKULL = register(new BlockItem(builder(), Blocks.WITHER_SKELETON_SKULL, Blocks.WITHER_SKELETON_WALL_SKULL));
+ public static final Item PLAYER_HEAD = register(new PlayerHeadItem(builder(), Blocks.PLAYER_HEAD, Blocks.PLAYER_WALL_HEAD));
+ public static final Item ZOMBIE_HEAD = register(new BlockItem(builder(), Blocks.ZOMBIE_HEAD, Blocks.ZOMBIE_WALL_HEAD));
+ public static final Item CREEPER_HEAD = register(new BlockItem(builder(), Blocks.CREEPER_HEAD, Blocks.CREEPER_WALL_HEAD));
+ public static final Item DRAGON_HEAD = register(new BlockItem(builder(), Blocks.DRAGON_HEAD, Blocks.DRAGON_WALL_HEAD));
+ public static final Item PIGLIN_HEAD = register(new BlockItem(builder(), Blocks.PIGLIN_HEAD, Blocks.PIGLIN_WALL_HEAD));
public static final Item NETHER_STAR = register(new Item("nether_star", builder()));
public static final Item PUMPKIN_PIE = register(new Item("pumpkin_pie", builder()));
public static final Item FIREWORK_ROCKET = register(new FireworkRocketItem("firework_rocket", builder()));
@@ -1171,29 +1170,29 @@ public final class Items {
public static final Item COMMAND_BLOCK_MINECART = register(new Item("command_block_minecart", builder().stackSize(1)));
public static final Item MUTTON = register(new Item("mutton", builder()));
public static final Item COOKED_MUTTON = register(new Item("cooked_mutton", builder()));
- public static final Item WHITE_BANNER = register(new BannerItem("white_banner", builder().stackSize(16)));
- public static final Item ORANGE_BANNER = register(new BannerItem("orange_banner", builder().stackSize(16)));
- public static final Item MAGENTA_BANNER = register(new BannerItem("magenta_banner", builder().stackSize(16)));
- public static final Item LIGHT_BLUE_BANNER = register(new BannerItem("light_blue_banner", builder().stackSize(16)));
- public static final Item YELLOW_BANNER = register(new BannerItem("yellow_banner", builder().stackSize(16)));
- public static final Item LIME_BANNER = register(new BannerItem("lime_banner", builder().stackSize(16)));
- public static final Item PINK_BANNER = register(new BannerItem("pink_banner", builder().stackSize(16)));
- public static final Item GRAY_BANNER = register(new BannerItem("gray_banner", builder().stackSize(16)));
- public static final Item LIGHT_GRAY_BANNER = register(new BannerItem("light_gray_banner", builder().stackSize(16)));
- public static final Item CYAN_BANNER = register(new BannerItem("cyan_banner", builder().stackSize(16)));
- public static final Item PURPLE_BANNER = register(new BannerItem("purple_banner", builder().stackSize(16)));
- public static final Item BLUE_BANNER = register(new BannerItem("blue_banner", builder().stackSize(16)));
- public static final Item BROWN_BANNER = register(new BannerItem("brown_banner", builder().stackSize(16)));
- public static final Item GREEN_BANNER = register(new BannerItem("green_banner", builder().stackSize(16)));
- public static final Item RED_BANNER = register(new BannerItem("red_banner", builder().stackSize(16)));
- public static final Item BLACK_BANNER = register(new BannerItem("black_banner", builder().stackSize(16)));
+ public static final Item WHITE_BANNER = register(new BannerItem(builder().stackSize(16), Blocks.WHITE_BANNER, Blocks.WHITE_WALL_BANNER));
+ public static final Item ORANGE_BANNER = register(new BannerItem(builder().stackSize(16), Blocks.ORANGE_BANNER, Blocks.ORANGE_WALL_BANNER));
+ public static final Item MAGENTA_BANNER = register(new BannerItem(builder().stackSize(16), Blocks.MAGENTA_BANNER, Blocks.MAGENTA_WALL_BANNER));
+ public static final Item LIGHT_BLUE_BANNER = register(new BannerItem(builder().stackSize(16), Blocks.LIGHT_BLUE_BANNER, Blocks.LIGHT_BLUE_WALL_BANNER));
+ public static final Item YELLOW_BANNER = register(new BannerItem(builder().stackSize(16), Blocks.YELLOW_BANNER, Blocks.YELLOW_WALL_BANNER));
+ public static final Item LIME_BANNER = register(new BannerItem(builder().stackSize(16), Blocks.LIME_BANNER, Blocks.LIME_WALL_BANNER));
+ public static final Item PINK_BANNER = register(new BannerItem(builder().stackSize(16), Blocks.PINK_BANNER, Blocks.PINK_WALL_BANNER));
+ public static final Item GRAY_BANNER = register(new BannerItem(builder().stackSize(16), Blocks.GRAY_BANNER, Blocks.GRAY_WALL_BANNER));
+ public static final Item LIGHT_GRAY_BANNER = register(new BannerItem(builder().stackSize(16), Blocks.LIGHT_GRAY_BANNER, Blocks.LIGHT_GRAY_WALL_BANNER));
+ public static final Item CYAN_BANNER = register(new BannerItem(builder().stackSize(16), Blocks.CYAN_BANNER, Blocks.CYAN_WALL_BANNER));
+ public static final Item PURPLE_BANNER = register(new BannerItem(builder().stackSize(16), Blocks.PURPLE_BANNER, Blocks.PURPLE_WALL_BANNER));
+ public static final Item BLUE_BANNER = register(new BannerItem(builder().stackSize(16), Blocks.BLUE_BANNER, Blocks.BLUE_WALL_BANNER));
+ public static final Item BROWN_BANNER = register(new BannerItem(builder().stackSize(16), Blocks.BROWN_BANNER, Blocks.BROWN_WALL_BANNER));
+ public static final Item GREEN_BANNER = register(new BannerItem(builder().stackSize(16), Blocks.GREEN_BANNER, Blocks.GREEN_WALL_BANNER));
+ public static final Item RED_BANNER = register(new BannerItem(builder().stackSize(16), Blocks.RED_BANNER, Blocks.RED_WALL_BANNER));
+ public static final Item BLACK_BANNER = register(new BannerItem(builder().stackSize(16), Blocks.BLACK_BANNER, Blocks.BLACK_WALL_BANNER));
public static final Item END_CRYSTAL = register(new Item("end_crystal", builder()));
public static final Item CHORUS_FRUIT = register(new Item("chorus_fruit", builder()));
public static final Item POPPED_CHORUS_FRUIT = register(new Item("popped_chorus_fruit", builder()));
- public static final Item TORCHFLOWER_SEEDS = register(new BlockItem("torchflower_seeds", builder()));
- public static final Item PITCHER_POD = register(new BlockItem("pitcher_pod", builder()));
+ public static final Item TORCHFLOWER_SEEDS = register(new BlockItem("torchflower_seeds", builder(), Blocks.TORCHFLOWER_CROP));
+ public static final Item PITCHER_POD = register(new BlockItem("pitcher_pod", builder(), Blocks.PITCHER_CROP));
public static final Item BEETROOT = register(new Item("beetroot", builder()));
- public static final Item BEETROOT_SEEDS = register(new BlockItem("beetroot_seeds", builder()));
+ public static final Item BEETROOT_SEEDS = register(new BlockItem("beetroot_seeds", builder(), Blocks.BEETROOTS));
public static final Item BEETROOT_SOUP = register(new Item("beetroot_soup", builder().stackSize(1)));
public static final Item DRAGON_BREATH = register(new Item("dragon_breath", builder()));
public static final Item SPLASH_POTION = register(new PotionItem("splash_potion", builder().stackSize(1)));
@@ -1210,6 +1209,8 @@ public final class Items {
public static final Item MUSIC_DISC_CAT = register(new Item("music_disc_cat", builder().stackSize(1)));
public static final Item MUSIC_DISC_BLOCKS = register(new Item("music_disc_blocks", builder().stackSize(1)));
public static final Item MUSIC_DISC_CHIRP = register(new Item("music_disc_chirp", builder().stackSize(1)));
+ public static final Item MUSIC_DISC_CREATOR = register(new Item("music_disc_creator", builder().stackSize(1)));
+ public static final Item MUSIC_DISC_CREATOR_MUSIC_BOX = register(new Item("music_disc_creator_music_box", builder().stackSize(1)));
public static final Item MUSIC_DISC_FAR = register(new Item("music_disc_far", builder().stackSize(1)));
public static final Item MUSIC_DISC_MALL = register(new Item("music_disc_mall", builder().stackSize(1)));
public static final Item MUSIC_DISC_MELLOHI = register(new Item("music_disc_mellohi", builder().stackSize(1)));
@@ -1222,6 +1223,7 @@ public final class Items {
public static final Item MUSIC_DISC_RELIC = register(new Item("music_disc_relic", builder().stackSize(1)));
public static final Item MUSIC_DISC_5 = register(new Item("music_disc_5", builder().stackSize(1)));
public static final Item MUSIC_DISC_PIGSTEP = register(new Item("music_disc_pigstep", builder().stackSize(1)));
+ public static final Item MUSIC_DISC_PRECIPICE = register(new Item("music_disc_precipice", builder().stackSize(1)));
public static final Item DISC_FRAGMENT_5 = register(new Item("disc_fragment_5", builder()));
public static final Item TRIDENT = register(new Item("trident", builder().stackSize(1).maxDamage(250).attackDamage(9.0)));
public static final Item PHANTOM_MEMBRANE = register(new Item("phantom_membrane", builder()));
@@ -1229,7 +1231,7 @@ public final class Items {
public static final Item HEART_OF_THE_SEA = register(new Item("heart_of_the_sea", builder()));
public static final Item CROSSBOW = register(new CrossbowItem("crossbow", builder().stackSize(1).maxDamage(465)));
public static final Item SUSPICIOUS_STEW = register(new Item("suspicious_stew", builder().stackSize(1)));
- public static final Item LOOM = register(new BlockItem("loom", builder()));
+ public static final Item LOOM = register(new BlockItem(builder(), Blocks.LOOM));
public static final Item FLOWER_BANNER_PATTERN = register(new Item("flower_banner_pattern", builder().stackSize(1)));
public static final Item CREEPER_BANNER_PATTERN = register(new Item("creeper_banner_pattern", builder().stackSize(1)));
public static final Item SKULL_BANNER_PATTERN = register(new Item("skull_banner_pattern", builder().stackSize(1)));
@@ -1239,69 +1241,69 @@ public final class Items {
public static final Item FLOW_BANNER_PATTERN = register(new Item("flow_banner_pattern", builder().stackSize(1)));
public static final Item GUSTER_BANNER_PATTERN = register(new Item("guster_banner_pattern", builder().stackSize(1)));
public static final Item GOAT_HORN = register(new GoatHornItem("goat_horn", builder().stackSize(1)));
- public static final Item COMPOSTER = register(new BlockItem("composter", builder()));
- public static final Item BARREL = register(new BlockItem("barrel", builder()));
- public static final Item SMOKER = register(new BlockItem("smoker", builder()));
- public static final Item BLAST_FURNACE = register(new BlockItem("blast_furnace", builder()));
- public static final Item CARTOGRAPHY_TABLE = register(new BlockItem("cartography_table", builder()));
- public static final Item FLETCHING_TABLE = register(new BlockItem("fletching_table", builder()));
- public static final Item GRINDSTONE = register(new BlockItem("grindstone", builder()));
- public static final Item SMITHING_TABLE = register(new BlockItem("smithing_table", builder()));
- public static final Item STONECUTTER = register(new BlockItem("stonecutter", builder()));
- public static final Item BELL = register(new BlockItem("bell", builder()));
- public static final Item LANTERN = register(new BlockItem("lantern", builder()));
- public static final Item SOUL_LANTERN = register(new BlockItem("soul_lantern", builder()));
- public static final Item SWEET_BERRIES = register(new BlockItem("sweet_berries", builder()));
- public static final Item GLOW_BERRIES = register(new BlockItem("glow_berries", builder()));
- public static final Item CAMPFIRE = register(new BlockItem("campfire", builder()));
- public static final Item SOUL_CAMPFIRE = register(new BlockItem("soul_campfire", builder()));
- public static final Item SHROOMLIGHT = register(new BlockItem("shroomlight", builder()));
+ public static final Item COMPOSTER = register(new BlockItem(builder(), Blocks.COMPOSTER));
+ public static final Item BARREL = register(new BlockItem(builder(), Blocks.BARREL));
+ public static final Item SMOKER = register(new BlockItem(builder(), Blocks.SMOKER));
+ public static final Item BLAST_FURNACE = register(new BlockItem(builder(), Blocks.BLAST_FURNACE));
+ public static final Item CARTOGRAPHY_TABLE = register(new BlockItem(builder(), Blocks.CARTOGRAPHY_TABLE));
+ public static final Item FLETCHING_TABLE = register(new BlockItem(builder(), Blocks.FLETCHING_TABLE));
+ public static final Item GRINDSTONE = register(new BlockItem(builder(), Blocks.GRINDSTONE));
+ public static final Item SMITHING_TABLE = register(new BlockItem(builder(), Blocks.SMITHING_TABLE));
+ public static final Item STONECUTTER = register(new BlockItem(builder(), Blocks.STONECUTTER));
+ public static final Item BELL = register(new BlockItem(builder(), Blocks.BELL));
+ public static final Item LANTERN = register(new BlockItem(builder(), Blocks.LANTERN));
+ public static final Item SOUL_LANTERN = register(new BlockItem(builder(), Blocks.SOUL_LANTERN));
+ public static final Item SWEET_BERRIES = register(new BlockItem("sweet_berries", builder(), Blocks.SWEET_BERRY_BUSH));
+ public static final Item GLOW_BERRIES = register(new BlockItem("glow_berries", builder(), Blocks.CAVE_VINES));
+ public static final Item CAMPFIRE = register(new BlockItem(builder(), Blocks.CAMPFIRE));
+ public static final Item SOUL_CAMPFIRE = register(new BlockItem(builder(), Blocks.SOUL_CAMPFIRE));
+ public static final Item SHROOMLIGHT = register(new BlockItem(builder(), Blocks.SHROOMLIGHT));
public static final Item HONEYCOMB = register(new Item("honeycomb", builder()));
- public static final Item BEE_NEST = register(new BlockItem("bee_nest", builder()));
- public static final Item BEEHIVE = register(new BlockItem("beehive", builder()));
+ public static final Item BEE_NEST = register(new BlockItem(builder(), Blocks.BEE_NEST));
+ public static final Item BEEHIVE = register(new BlockItem(builder(), Blocks.BEEHIVE));
public static final Item HONEY_BOTTLE = register(new Item("honey_bottle", builder().stackSize(16)));
- public static final Item HONEYCOMB_BLOCK = register(new BlockItem("honeycomb_block", builder()));
- public static final Item LODESTONE = register(new BlockItem("lodestone", builder()));
- public static final Item CRYING_OBSIDIAN = register(new BlockItem("crying_obsidian", builder()));
- public static final Item BLACKSTONE = register(new BlockItem("blackstone", builder()));
- public static final Item BLACKSTONE_SLAB = register(new BlockItem("blackstone_slab", builder()));
- public static final Item BLACKSTONE_STAIRS = register(new BlockItem("blackstone_stairs", builder()));
- public static final Item GILDED_BLACKSTONE = register(new BlockItem("gilded_blackstone", builder()));
- public static final Item POLISHED_BLACKSTONE = register(new BlockItem("polished_blackstone", builder()));
- public static final Item POLISHED_BLACKSTONE_SLAB = register(new BlockItem("polished_blackstone_slab", builder()));
- public static final Item POLISHED_BLACKSTONE_STAIRS = register(new BlockItem("polished_blackstone_stairs", builder()));
- public static final Item CHISELED_POLISHED_BLACKSTONE = register(new BlockItem("chiseled_polished_blackstone", builder()));
- public static final Item POLISHED_BLACKSTONE_BRICKS = register(new BlockItem("polished_blackstone_bricks", builder()));
- public static final Item POLISHED_BLACKSTONE_BRICK_SLAB = register(new BlockItem("polished_blackstone_brick_slab", builder()));
- public static final Item POLISHED_BLACKSTONE_BRICK_STAIRS = register(new BlockItem("polished_blackstone_brick_stairs", builder()));
- public static final Item CRACKED_POLISHED_BLACKSTONE_BRICKS = register(new BlockItem("cracked_polished_blackstone_bricks", builder()));
- public static final Item RESPAWN_ANCHOR = register(new BlockItem("respawn_anchor", builder()));
- public static final Item CANDLE = register(new BlockItem("candle", builder()));
- public static final Item WHITE_CANDLE = register(new BlockItem("white_candle", builder()));
- public static final Item ORANGE_CANDLE = register(new BlockItem("orange_candle", builder()));
- public static final Item MAGENTA_CANDLE = register(new BlockItem("magenta_candle", builder()));
- public static final Item LIGHT_BLUE_CANDLE = register(new BlockItem("light_blue_candle", builder()));
- public static final Item YELLOW_CANDLE = register(new BlockItem("yellow_candle", builder()));
- public static final Item LIME_CANDLE = register(new BlockItem("lime_candle", builder()));
- public static final Item PINK_CANDLE = register(new BlockItem("pink_candle", builder()));
- public static final Item GRAY_CANDLE = register(new BlockItem("gray_candle", builder()));
- public static final Item LIGHT_GRAY_CANDLE = register(new BlockItem("light_gray_candle", builder()));
- public static final Item CYAN_CANDLE = register(new BlockItem("cyan_candle", builder()));
- public static final Item PURPLE_CANDLE = register(new BlockItem("purple_candle", builder()));
- public static final Item BLUE_CANDLE = register(new BlockItem("blue_candle", builder()));
- public static final Item BROWN_CANDLE = register(new BlockItem("brown_candle", builder()));
- public static final Item GREEN_CANDLE = register(new BlockItem("green_candle", builder()));
- public static final Item RED_CANDLE = register(new BlockItem("red_candle", builder()));
- public static final Item BLACK_CANDLE = register(new BlockItem("black_candle", builder()));
- public static final Item SMALL_AMETHYST_BUD = register(new BlockItem("small_amethyst_bud", builder()));
- public static final Item MEDIUM_AMETHYST_BUD = register(new BlockItem("medium_amethyst_bud", builder()));
- public static final Item LARGE_AMETHYST_BUD = register(new BlockItem("large_amethyst_bud", builder()));
- public static final Item AMETHYST_CLUSTER = register(new BlockItem("amethyst_cluster", builder()));
- public static final Item POINTED_DRIPSTONE = register(new BlockItem("pointed_dripstone", builder()));
- public static final Item OCHRE_FROGLIGHT = register(new BlockItem("ochre_froglight", builder()));
- public static final Item VERDANT_FROGLIGHT = register(new BlockItem("verdant_froglight", builder()));
- public static final Item PEARLESCENT_FROGLIGHT = register(new BlockItem("pearlescent_froglight", builder()));
- public static final Item FROGSPAWN = register(new BlockItem("frogspawn", builder()));
+ public static final Item HONEYCOMB_BLOCK = register(new BlockItem(builder(), Blocks.HONEYCOMB_BLOCK));
+ public static final Item LODESTONE = register(new BlockItem(builder(), Blocks.LODESTONE));
+ public static final Item CRYING_OBSIDIAN = register(new BlockItem(builder(), Blocks.CRYING_OBSIDIAN));
+ public static final Item BLACKSTONE = register(new BlockItem(builder(), Blocks.BLACKSTONE));
+ public static final Item BLACKSTONE_SLAB = register(new BlockItem(builder(), Blocks.BLACKSTONE_SLAB));
+ public static final Item BLACKSTONE_STAIRS = register(new BlockItem(builder(), Blocks.BLACKSTONE_STAIRS));
+ public static final Item GILDED_BLACKSTONE = register(new BlockItem(builder(), Blocks.GILDED_BLACKSTONE));
+ public static final Item POLISHED_BLACKSTONE = register(new BlockItem(builder(), Blocks.POLISHED_BLACKSTONE));
+ public static final Item POLISHED_BLACKSTONE_SLAB = register(new BlockItem(builder(), Blocks.POLISHED_BLACKSTONE_SLAB));
+ public static final Item POLISHED_BLACKSTONE_STAIRS = register(new BlockItem(builder(), Blocks.POLISHED_BLACKSTONE_STAIRS));
+ public static final Item CHISELED_POLISHED_BLACKSTONE = register(new BlockItem(builder(), Blocks.CHISELED_POLISHED_BLACKSTONE));
+ public static final Item POLISHED_BLACKSTONE_BRICKS = register(new BlockItem(builder(), Blocks.POLISHED_BLACKSTONE_BRICKS));
+ public static final Item POLISHED_BLACKSTONE_BRICK_SLAB = register(new BlockItem(builder(), Blocks.POLISHED_BLACKSTONE_BRICK_SLAB));
+ public static final Item POLISHED_BLACKSTONE_BRICK_STAIRS = register(new BlockItem(builder(), Blocks.POLISHED_BLACKSTONE_BRICK_STAIRS));
+ public static final Item CRACKED_POLISHED_BLACKSTONE_BRICKS = register(new BlockItem(builder(), Blocks.CRACKED_POLISHED_BLACKSTONE_BRICKS));
+ public static final Item RESPAWN_ANCHOR = register(new BlockItem(builder(), Blocks.RESPAWN_ANCHOR));
+ public static final Item CANDLE = register(new BlockItem(builder(), Blocks.CANDLE));
+ public static final Item WHITE_CANDLE = register(new BlockItem(builder(), Blocks.WHITE_CANDLE));
+ public static final Item ORANGE_CANDLE = register(new BlockItem(builder(), Blocks.ORANGE_CANDLE));
+ public static final Item MAGENTA_CANDLE = register(new BlockItem(builder(), Blocks.MAGENTA_CANDLE));
+ public static final Item LIGHT_BLUE_CANDLE = register(new BlockItem(builder(), Blocks.LIGHT_BLUE_CANDLE));
+ public static final Item YELLOW_CANDLE = register(new BlockItem(builder(), Blocks.YELLOW_CANDLE));
+ public static final Item LIME_CANDLE = register(new BlockItem(builder(), Blocks.LIME_CANDLE));
+ public static final Item PINK_CANDLE = register(new BlockItem(builder(), Blocks.PINK_CANDLE));
+ public static final Item GRAY_CANDLE = register(new BlockItem(builder(), Blocks.GRAY_CANDLE));
+ public static final Item LIGHT_GRAY_CANDLE = register(new BlockItem(builder(), Blocks.LIGHT_GRAY_CANDLE));
+ public static final Item CYAN_CANDLE = register(new BlockItem(builder(), Blocks.CYAN_CANDLE));
+ public static final Item PURPLE_CANDLE = register(new BlockItem(builder(), Blocks.PURPLE_CANDLE));
+ public static final Item BLUE_CANDLE = register(new BlockItem(builder(), Blocks.BLUE_CANDLE));
+ public static final Item BROWN_CANDLE = register(new BlockItem(builder(), Blocks.BROWN_CANDLE));
+ public static final Item GREEN_CANDLE = register(new BlockItem(builder(), Blocks.GREEN_CANDLE));
+ public static final Item RED_CANDLE = register(new BlockItem(builder(), Blocks.RED_CANDLE));
+ public static final Item BLACK_CANDLE = register(new BlockItem(builder(), Blocks.BLACK_CANDLE));
+ public static final Item SMALL_AMETHYST_BUD = register(new BlockItem(builder(), Blocks.SMALL_AMETHYST_BUD));
+ public static final Item MEDIUM_AMETHYST_BUD = register(new BlockItem(builder(), Blocks.MEDIUM_AMETHYST_BUD));
+ public static final Item LARGE_AMETHYST_BUD = register(new BlockItem(builder(), Blocks.LARGE_AMETHYST_BUD));
+ public static final Item AMETHYST_CLUSTER = register(new BlockItem(builder(), Blocks.AMETHYST_CLUSTER));
+ public static final Item POINTED_DRIPSTONE = register(new BlockItem(builder(), Blocks.POINTED_DRIPSTONE));
+ public static final Item OCHRE_FROGLIGHT = register(new BlockItem(builder(), Blocks.OCHRE_FROGLIGHT));
+ public static final Item VERDANT_FROGLIGHT = register(new BlockItem(builder(), Blocks.VERDANT_FROGLIGHT));
+ public static final Item PEARLESCENT_FROGLIGHT = register(new BlockItem(builder(), Blocks.PEARLESCENT_FROGLIGHT));
+ public static final Item FROGSPAWN = register(new BlockItem(builder(), Blocks.FROGSPAWN));
public static final Item ECHO_SHARD = register(new Item("echo_shard", builder()));
public static final Item BRUSH = register(new Item("brush", builder().stackSize(1).maxDamage(64)));
public static final Item NETHERITE_UPGRADE_SMITHING_TEMPLATE = register(new Item("netherite_upgrade_smithing_template", builder()));
@@ -1346,27 +1348,27 @@ public final class Items {
public static final Item SHELTER_POTTERY_SHERD = register(new Item("shelter_pottery_sherd", builder()));
public static final Item SKULL_POTTERY_SHERD = register(new Item("skull_pottery_sherd", builder()));
public static final Item SNORT_POTTERY_SHERD = register(new Item("snort_pottery_sherd", builder()));
- public static final Item COPPER_GRATE = register(new BlockItem("copper_grate", builder()));
- public static final Item EXPOSED_COPPER_GRATE = register(new BlockItem("exposed_copper_grate", builder()));
- public static final Item WEATHERED_COPPER_GRATE = register(new BlockItem("weathered_copper_grate", builder()));
- public static final Item OXIDIZED_COPPER_GRATE = register(new BlockItem("oxidized_copper_grate", builder()));
- public static final Item WAXED_COPPER_GRATE = register(new BlockItem("waxed_copper_grate", builder()));
- public static final Item WAXED_EXPOSED_COPPER_GRATE = register(new BlockItem("waxed_exposed_copper_grate", builder()));
- public static final Item WAXED_WEATHERED_COPPER_GRATE = register(new BlockItem("waxed_weathered_copper_grate", builder()));
- public static final Item WAXED_OXIDIZED_COPPER_GRATE = register(new BlockItem("waxed_oxidized_copper_grate", builder()));
- public static final Item COPPER_BULB = register(new BlockItem("copper_bulb", builder()));
- public static final Item EXPOSED_COPPER_BULB = register(new BlockItem("exposed_copper_bulb", builder()));
- public static final Item WEATHERED_COPPER_BULB = register(new BlockItem("weathered_copper_bulb", builder()));
- public static final Item OXIDIZED_COPPER_BULB = register(new BlockItem("oxidized_copper_bulb", builder()));
- public static final Item WAXED_COPPER_BULB = register(new BlockItem("waxed_copper_bulb", builder()));
- public static final Item WAXED_EXPOSED_COPPER_BULB = register(new BlockItem("waxed_exposed_copper_bulb", builder()));
- public static final Item WAXED_WEATHERED_COPPER_BULB = register(new BlockItem("waxed_weathered_copper_bulb", builder()));
- public static final Item WAXED_OXIDIZED_COPPER_BULB = register(new BlockItem("waxed_oxidized_copper_bulb", builder()));
- public static final Item TRIAL_SPAWNER = register(new BlockItem("trial_spawner", builder()));
+ public static final Item COPPER_GRATE = register(new BlockItem(builder(), Blocks.COPPER_GRATE));
+ public static final Item EXPOSED_COPPER_GRATE = register(new BlockItem(builder(), Blocks.EXPOSED_COPPER_GRATE));
+ public static final Item WEATHERED_COPPER_GRATE = register(new BlockItem(builder(), Blocks.WEATHERED_COPPER_GRATE));
+ public static final Item OXIDIZED_COPPER_GRATE = register(new BlockItem(builder(), Blocks.OXIDIZED_COPPER_GRATE));
+ public static final Item WAXED_COPPER_GRATE = register(new BlockItem(builder(), Blocks.WAXED_COPPER_GRATE));
+ public static final Item WAXED_EXPOSED_COPPER_GRATE = register(new BlockItem(builder(), Blocks.WAXED_EXPOSED_COPPER_GRATE));
+ public static final Item WAXED_WEATHERED_COPPER_GRATE = register(new BlockItem(builder(), Blocks.WAXED_WEATHERED_COPPER_GRATE));
+ public static final Item WAXED_OXIDIZED_COPPER_GRATE = register(new BlockItem(builder(), Blocks.WAXED_OXIDIZED_COPPER_GRATE));
+ public static final Item COPPER_BULB = register(new BlockItem(builder(), Blocks.COPPER_BULB));
+ public static final Item EXPOSED_COPPER_BULB = register(new BlockItem(builder(), Blocks.EXPOSED_COPPER_BULB));
+ public static final Item WEATHERED_COPPER_BULB = register(new BlockItem(builder(), Blocks.WEATHERED_COPPER_BULB));
+ public static final Item OXIDIZED_COPPER_BULB = register(new BlockItem(builder(), Blocks.OXIDIZED_COPPER_BULB));
+ public static final Item WAXED_COPPER_BULB = register(new BlockItem(builder(), Blocks.WAXED_COPPER_BULB));
+ public static final Item WAXED_EXPOSED_COPPER_BULB = register(new BlockItem(builder(), Blocks.WAXED_EXPOSED_COPPER_BULB));
+ public static final Item WAXED_WEATHERED_COPPER_BULB = register(new BlockItem(builder(), Blocks.WAXED_WEATHERED_COPPER_BULB));
+ public static final Item WAXED_OXIDIZED_COPPER_BULB = register(new BlockItem(builder(), Blocks.WAXED_OXIDIZED_COPPER_BULB));
+ public static final Item TRIAL_SPAWNER = register(new BlockItem(builder(), Blocks.TRIAL_SPAWNER));
public static final Item TRIAL_KEY = register(new Item("trial_key", builder()));
public static final Item OMINOUS_TRIAL_KEY = register(new Item("ominous_trial_key", builder()));
- public static final Item VAULT = register(new BlockItem("vault", builder()));
- public static final Item OMINOUS_BOTTLE = register(new Item("ominous_bottle", builder()));
+ public static final Item VAULT = register(new BlockItem(builder(), Blocks.VAULT));
+ public static final Item OMINOUS_BOTTLE = register(new OminousBottleItem("ominous_bottle", builder()));
public static final Item BREEZE_ROD = register(new Item("breeze_rod", builder()));
public static final int AIR_ID = AIR.javaId();
@@ -1377,11 +1379,7 @@ public final class Items {
public static T register(T item, int id) {
item.setJavaId(id);
- // This makes sure that the array is large enough to put the java item at the correct location
- if (Registries.JAVA_ITEMS.get().size() <= id) {
- Registries.JAVA_ITEMS.get().addAll(Collections.nCopies(id - Registries.JAVA_ITEMS.get().size() + 1, AIR));
- }
- Registries.JAVA_ITEMS.get().set(id, item);
+ Registries.JAVA_ITEMS.registerWithAnyIndex(id, item, AIR);
Registries.JAVA_ITEM_IDENTIFIERS.register(item.javaIdentifier(), item);
return item;
}
diff --git a/core/src/main/java/org/geysermc/geyser/item/enchantment/Enchantment.java b/core/src/main/java/org/geysermc/geyser/item/enchantment/Enchantment.java
new file mode 100644
index 000000000..c5c0d2611
--- /dev/null
+++ b/core/src/main/java/org/geysermc/geyser/item/enchantment/Enchantment.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2024 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.item.enchantment;
+
+import org.checkerframework.checker.nullness.qual.Nullable;
+import org.cloudburstmc.nbt.NbtMap;
+import org.geysermc.geyser.inventory.item.BedrockEnchantment;
+import org.geysermc.geyser.session.cache.tags.EnchantmentTag;
+import org.geysermc.geyser.session.cache.tags.ItemTag;
+import org.geysermc.geyser.translator.text.MessageTranslator;
+import org.geysermc.geyser.util.MinecraftKey;
+import org.geysermc.mcprotocollib.protocol.data.game.RegistryEntry;
+
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @param description only populated if {@link #bedrockEnchantment()} is not null.
+ * @param anvilCost also as a rarity multiplier
+ */
+public record Enchantment(String identifier,
+ Set effects,
+ ItemTag supportedItems,
+ int maxLevel,
+ String description,
+ int anvilCost,
+ @Nullable EnchantmentTag exclusiveSet,
+ @Nullable BedrockEnchantment bedrockEnchantment) {
+
+ // Implementation note: I have a feeling the tags can be a list of items, because in vanilla they're HolderSet classes.
+ // I'm not sure how that's wired over the network, so we'll put it off.
+ public static Enchantment read(RegistryEntry entry) {
+ NbtMap data = entry.getData();
+ Set effects = readEnchantmentComponents(data.getCompound("effects"));
+ String supportedItems = data.getString("supported_items").substring(1); // Remove '#' at beginning that indicates tag
+ int maxLevel = data.getInt("max_level");
+ int anvilCost = data.getInt("anvil_cost");
+ String exclusiveSet = data.getString("exclusive_set", null);
+ EnchantmentTag exclusiveSetTag = exclusiveSet == null ? null : EnchantmentTag.ALL_ENCHANTMENT_TAGS.get(MinecraftKey.key(exclusiveSet.substring(1)));
+ BedrockEnchantment bedrockEnchantment = BedrockEnchantment.getByJavaIdentifier(entry.getId().asString());
+ String description = bedrockEnchantment == null ? MessageTranslator.deserializeDescription(data) : null;
+
+ return new Enchantment(entry.getId().asString(), effects, ItemTag.ALL_ITEM_TAGS.get(MinecraftKey.key(supportedItems)), maxLevel,
+ description, anvilCost, exclusiveSetTag, bedrockEnchantment);
+ }
+
+ private static Set readEnchantmentComponents(NbtMap effects) {
+ Set components = new HashSet<>();
+ for (Map.Entry entry : effects.entrySet()) {
+ switch (entry.getKey()) {
+ case "minecraft:prevent_armor_change" -> components.add(EnchantmentComponent.PREVENT_ARMOR_CHANGE);
+ }
+ }
+ return Set.copyOf(components); // Also ensures any empty sets are consolidated
+ }
+}
diff --git a/core/src/main/java/org/geysermc/geyser/item/enchantment/EnchantmentComponent.java b/core/src/main/java/org/geysermc/geyser/item/enchantment/EnchantmentComponent.java
new file mode 100644
index 000000000..66d110f98
--- /dev/null
+++ b/core/src/main/java/org/geysermc/geyser/item/enchantment/EnchantmentComponent.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2024 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.item.enchantment;
+
+public class EnchantmentComponent {
+ /**
+ * Singleton with no additional data
+ */
+ public static final EnchantmentComponent PREVENT_ARMOR_CHANGE = new EnchantmentComponent();
+}
diff --git a/core/src/main/java/org/geysermc/geyser/item/type/ArmorItem.java b/core/src/main/java/org/geysermc/geyser/item/type/ArmorItem.java
index fc0dd3ba4..0a25a8d4f 100644
--- a/core/src/main/java/org/geysermc/geyser/item/type/ArmorItem.java
+++ b/core/src/main/java/org/geysermc/geyser/item/type/ArmorItem.java
@@ -51,14 +51,15 @@ public class ArmorItem extends Item {
ArmorTrim trim = components.get(DataComponentType.TRIM);
if (trim != null) {
- // discard custom trim patterns/materials to prevent visual glitches on bedrock
- if (trim.material().isCustom() || trim.pattern().isCustom()) {
- return;
- }
-
TrimMaterial material = session.getRegistryCache().trimMaterials().byId(trim.material().id());
TrimPattern pattern = session.getRegistryCache().trimPatterns().byId(trim.pattern().id());
+ // discard custom trim patterns/materials to prevent visual glitches on bedrock
+ if (!getNamespace(material.getMaterialId()).equals("minecraft")
+ || !getNamespace(pattern.getPatternId()).equals("minecraft")) {
+ return;
+ }
+
NbtMapBuilder trimBuilder = NbtMap.builder();
// bedrock has an uppercase first letter key, and the value is not namespaced
trimBuilder.put("Material", material.getMaterialId());
@@ -71,4 +72,13 @@ public class ArmorItem extends Item {
public boolean isValidRepairItem(Item other) {
return material.getRepairIngredient() == other;
}
+
+ // TODO maybe some kind of namespace util?
+ private static String getNamespace(String identifier) {
+ int i = identifier.indexOf(':');
+ if (i >= 0) {
+ return identifier.substring(0, i);
+ }
+ return "minecraft";
+ }
}
diff --git a/core/src/main/java/org/geysermc/geyser/item/type/ArrowItem.java b/core/src/main/java/org/geysermc/geyser/item/type/ArrowItem.java
index f2548e170..4e4f1830e 100644
--- a/core/src/main/java/org/geysermc/geyser/item/type/ArrowItem.java
+++ b/core/src/main/java/org/geysermc/geyser/item/type/ArrowItem.java
@@ -25,11 +25,10 @@
package org.geysermc.geyser.item.type;
-import it.unimi.dsi.fastutil.ints.Int2ObjectMaps;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
import org.geysermc.geyser.inventory.GeyserItemStack;
-import org.geysermc.geyser.inventory.item.TippedArrowPotion;
+import org.geysermc.geyser.inventory.item.Potion;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.registry.type.ItemMappings;
@@ -43,13 +42,18 @@ public class ArrowItem extends Item {
@Override
public @NonNull GeyserItemStack translateToJava(@NonNull ItemData itemData, @NonNull ItemMapping mapping, @NonNull ItemMappings mappings) {
- TippedArrowPotion tippedArrowPotion = TippedArrowPotion.getByBedrockId(itemData.getDamage());
+ Potion potion = Potion.getByTippedArrowDamage(itemData.getDamage());
GeyserItemStack itemStack = super.translateToJava(itemData, mapping, mappings);
- if (tippedArrowPotion != null) {
+ if (potion != null) {
itemStack = Items.TIPPED_ARROW.newItemStack(itemStack.getAmount(), itemStack.getComponents());
- PotionContents contents = new PotionContents(tippedArrowPotion.ordinal(), -1, Int2ObjectMaps.emptyMap());
+ PotionContents contents = potion.toComponent();
itemStack.getOrCreateComponents().put(DataComponentType.POTION_CONTENTS, contents);
}
return itemStack;
}
+
+ @Override
+ public boolean ignoreDamage() {
+ return true;
+ }
}
diff --git a/core/src/main/java/org/geysermc/geyser/item/type/BannerItem.java b/core/src/main/java/org/geysermc/geyser/item/type/BannerItem.java
index 6c2678db9..6ec0da8ed 100644
--- a/core/src/main/java/org/geysermc/geyser/item/type/BannerItem.java
+++ b/core/src/main/java/org/geysermc/geyser/item/type/BannerItem.java
@@ -26,6 +26,7 @@
package org.geysermc.geyser.item.type;
import it.unimi.dsi.fastutil.Pair;
+import net.kyori.adventure.key.Key;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.Style;
import net.kyori.adventure.text.format.TextColor;
@@ -35,12 +36,13 @@ import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.nbt.NbtType;
import org.geysermc.geyser.inventory.item.BannerPattern;
import org.geysermc.geyser.inventory.item.DyeColor;
+import org.geysermc.geyser.level.block.type.Block;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.session.cache.registry.JavaRegistry;
import org.geysermc.geyser.translator.item.BedrockItemBuilder;
+import org.geysermc.geyser.util.MinecraftKey;
import org.geysermc.mcprotocollib.protocol.data.game.Holder;
-import org.geysermc.mcprotocollib.protocol.data.game.Identifier;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.BannerPatternLayer;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents;
@@ -59,9 +61,6 @@ public class BannerItem extends BlockItem {
*/
private static final List> OMINOUS_BANNER_PATTERN;
- // TODO fix - we somehow need to be able to get the sessions banner pattern registry, which we don't have where we need this :/
- private static final int[] ominousBannerPattern = new int[] { 21, 29, 30, 1, 34, 15, 3, 1 };
-
static {
// Construct what an ominous banner is supposed to look like
OMINOUS_BANNER_PATTERN = List.of(
@@ -108,7 +107,7 @@ public class BannerItem extends BlockItem {
if (color != pair.right()) {
return false;
}
- String id = Identifier.formalize(patternLayer.getString("pattern")); // Ouch
+ Key id = MinecraftKey.key(patternLayer.getString("pattern")); // Ouch
BannerPattern bannerPattern = BannerPattern.getByJavaIdentifier(id);
if (bannerPattern != pair.left()) {
return false;
@@ -145,8 +144,8 @@ public class BannerItem extends BlockItem {
} else {
List patternList = new ArrayList<>(patterns.size());
for (BannerPatternLayer patternLayer : patterns) {
- patternLayer.getPattern().ifId(holder -> {
- BannerPattern bannerPattern = session.getRegistryCache().bannerPatterns().byId(holder.id());
+ patternLayer.getPattern().ifId(id -> {
+ BannerPattern bannerPattern = session.getRegistryCache().bannerPatterns().byId(id);
if (bannerPattern != null) {
NbtMap tag = NbtMap.builder()
.putString("Pattern", bannerPattern.getBedrockIdentifier())
@@ -168,7 +167,7 @@ public class BannerItem extends BlockItem {
*/
private static NbtMap getBedrockBannerPattern(NbtMap pattern) {
// ViaVersion 1.20.4 -> 1.20.5 can send without the namespace
- BannerPattern bannerPattern = BannerPattern.getByJavaIdentifier(Identifier.formalize(pattern.getString("pattern")));
+ BannerPattern bannerPattern = BannerPattern.getByJavaIdentifier(MinecraftKey.key(pattern.getString("pattern")));
DyeColor dyeColor = DyeColor.getByJavaIdentifier(pattern.getString("color"));
if (bannerPattern == null || dyeColor == null) {
return null;
@@ -199,8 +198,8 @@ public class BannerItem extends BlockItem {
return null;
}
- public BannerItem(String javaIdentifier, Builder builder) {
- super(javaIdentifier, builder);
+ public BannerItem(Builder builder, Block block, Block... otherBlocks) {
+ super(builder, block, otherBlocks);
}
@Override
@@ -214,20 +213,22 @@ public class BannerItem extends BlockItem {
}
@Override
- public void translateNbtToJava(@NonNull NbtMap bedrockTag, @NonNull DataComponents components, @NonNull ItemMapping mapping) {
- super.translateNbtToJava(bedrockTag, components, mapping);
+ public void translateNbtToJava(@NonNull GeyserSession session, @NonNull NbtMap bedrockTag, @NonNull DataComponents components, @NonNull ItemMapping mapping) {
+ super.translateNbtToJava(session, bedrockTag, components, mapping);
if (bedrockTag.getInt("Type") == 1) {
// Ominous banner pattern
List patternLayers = new ArrayList<>();
- for (int i = 0; i < ominousBannerPattern.length; i++) {
- patternLayers.add(new BannerPatternLayer(Holder.ofId(ominousBannerPattern[i]), OMINOUS_BANNER_PATTERN.get(i).right().ordinal()));
+ for (int i = 0; i < OMINOUS_BANNER_PATTERN.size(); i++) {
+ var pair = OMINOUS_BANNER_PATTERN.get(i);
+ patternLayers.add(new BannerPatternLayer(Holder.ofId(session.getRegistryCache().bannerPatterns().byValue(pair.left())),
+ pair.right().ordinal()));
}
components.put(DataComponentType.BANNER_PATTERNS, patternLayers);
components.put(DataComponentType.HIDE_ADDITIONAL_TOOLTIP, Unit.INSTANCE);
components.put(DataComponentType.ITEM_NAME, Component
- .translatable("block.minecraft.ominous_banner") // thank god this works
+ .translatable("block.minecraft.ominous_banner")
.style(Style.style(TextColor.color(16755200)))
);
}
diff --git a/core/src/main/java/org/geysermc/geyser/item/type/BlockItem.java b/core/src/main/java/org/geysermc/geyser/item/type/BlockItem.java
index 0dbf0971a..30a31a100 100644
--- a/core/src/main/java/org/geysermc/geyser/item/type/BlockItem.java
+++ b/core/src/main/java/org/geysermc/geyser/item/type/BlockItem.java
@@ -25,11 +25,26 @@
package org.geysermc.geyser.item.type;
-/**
- * TODO needed?
- */
+import org.geysermc.geyser.level.block.type.Block;
+
public class BlockItem extends Item {
- public BlockItem(String javaIdentifier, Builder builder) {
+ public BlockItem(Builder builder, Block block, Block... otherBlocks) {
+ super(block.javaIdentifier().value(), builder);
+
+ // Ensure this item can be looked up by its block(s)
+ registerBlock(block, this);
+ for (Block otherBlock : otherBlocks) {
+ registerBlock(otherBlock, this);
+ }
+ }
+
+ // Use this constructor if the item name is not the same as its primary block
+ public BlockItem(String javaIdentifier, Builder builder, Block block, Block... otherBlocks) {
super(javaIdentifier, builder);
+
+ registerBlock(block, this);
+ for (Block otherBlock : otherBlocks) {
+ registerBlock(otherBlock, this);
+ }
}
}
diff --git a/core/src/main/java/org/geysermc/geyser/item/type/DecoratedPotItem.java b/core/src/main/java/org/geysermc/geyser/item/type/DecoratedPotItem.java
index 2631bf9be..578ba4063 100644
--- a/core/src/main/java/org/geysermc/geyser/item/type/DecoratedPotItem.java
+++ b/core/src/main/java/org/geysermc/geyser/item/type/DecoratedPotItem.java
@@ -27,6 +27,7 @@ package org.geysermc.geyser.item.type;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.cloudburstmc.nbt.NbtType;
+import org.geysermc.geyser.level.block.type.Block;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.item.BedrockItemBuilder;
@@ -38,8 +39,8 @@ import java.util.List;
public class DecoratedPotItem extends BlockItem {
- public DecoratedPotItem(String javaIdentifier, Builder builder) {
- super(javaIdentifier, builder);
+ public DecoratedPotItem(Builder builder, Block block, Block... otherBlocks) {
+ super(builder, block, otherBlocks);
}
@Override
diff --git a/core/src/main/java/org/geysermc/geyser/item/type/DyeableArmorItem.java b/core/src/main/java/org/geysermc/geyser/item/type/DyeableArmorItem.java
index b2dbb95e5..8c63eaeb0 100644
--- a/core/src/main/java/org/geysermc/geyser/item/type/DyeableArmorItem.java
+++ b/core/src/main/java/org/geysermc/geyser/item/type/DyeableArmorItem.java
@@ -29,9 +29,7 @@ import org.checkerframework.checker.nullness.qual.NonNull;
import org.geysermc.geyser.item.ArmorMaterial;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.item.BedrockItemBuilder;
-import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents;
-import org.geysermc.mcprotocollib.protocol.data.game.item.component.DyedItemColor;
public class DyeableArmorItem extends ArmorItem {
public DyeableArmorItem(String javaIdentifier, ArmorMaterial material, Builder builder) {
@@ -44,9 +42,6 @@ public class DyeableArmorItem extends ArmorItem {
// Note that this is handled as of 1.20.5 in the ItemColors class.
// But horse leather armor and body leather armor are now both armor items. So it works!
- DyedItemColor dyedItemColor = components.get(DataComponentType.DYED_COLOR);
- if (dyedItemColor != null) {
- builder.putInt("customColor", dyedItemColor.getRgb());
- }
+ translateDyedColor(components, builder);
}
}
diff --git a/core/src/main/java/org/geysermc/geyser/item/type/EnchantedBookItem.java b/core/src/main/java/org/geysermc/geyser/item/type/EnchantedBookItem.java
index 98e98b4b8..8b0f3e22e 100644
--- a/core/src/main/java/org/geysermc/geyser/item/type/EnchantedBookItem.java
+++ b/core/src/main/java/org/geysermc/geyser/item/type/EnchantedBookItem.java
@@ -31,7 +31,8 @@ import org.checkerframework.checker.nullness.qual.NonNull;
import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.nbt.NbtType;
import org.geysermc.geyser.GeyserImpl;
-import org.geysermc.geyser.inventory.item.Enchantment;
+import org.geysermc.geyser.inventory.item.BedrockEnchantment;
+import org.geysermc.geyser.item.enchantment.Enchantment;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.item.BedrockItemBuilder;
@@ -69,8 +70,8 @@ public class EnchantedBookItem extends Item {
}
@Override
- public void translateNbtToJava(@NonNull NbtMap bedrockTag, @NonNull DataComponents components, @NonNull ItemMapping mapping) {
- super.translateNbtToJava(bedrockTag, components, mapping);
+ public void translateNbtToJava(@NonNull GeyserSession session, @NonNull NbtMap bedrockTag, @NonNull DataComponents components, @NonNull ItemMapping mapping) {
+ super.translateNbtToJava(session, bedrockTag, components, mapping);
List enchantmentTag = bedrockTag.getList("ench", NbtType.COMPOUND);
if (enchantmentTag != null) {
@@ -78,11 +79,16 @@ public class EnchantedBookItem extends Item {
for (NbtMap bedrockEnchantment : enchantmentTag) {
short bedrockId = bedrockEnchantment.getShort("id");
- Enchantment enchantment = Enchantment.getByBedrockId(bedrockId);
+ BedrockEnchantment enchantment = BedrockEnchantment.getByBedrockId(bedrockId);
if (enchantment != null) {
- int level = bedrockEnchantment.getShort("lvl", (short) 1);
- // TODO
- javaEnchantments.put(Enchantment.JavaEnchantment.valueOf(enchantment.name()).ordinal(), level);
+ List enchantments = session.getRegistryCache().enchantments().values();
+ for (int i = 0; i < enchantments.size(); i++) {
+ if (enchantments.get(i).bedrockEnchantment() == enchantment) {
+ int level = bedrockEnchantment.getShort("lvl", (short) 1);
+ javaEnchantments.put(i, level);
+ break;
+ }
+ }
} else {
GeyserImpl.getInstance().getLogger().debug("Unknown bedrock enchantment: " + bedrockId);
}
diff --git a/core/src/main/java/org/geysermc/geyser/item/type/FilledMapItem.java b/core/src/main/java/org/geysermc/geyser/item/type/FilledMapItem.java
index 70a04b863..e571a796a 100644
--- a/core/src/main/java/org/geysermc/geyser/item/type/FilledMapItem.java
+++ b/core/src/main/java/org/geysermc/geyser/item/type/FilledMapItem.java
@@ -51,6 +51,7 @@ public class FilledMapItem extends MapItem {
switch (mapColor) {
case 3830373 -> builder.damage(3); // Ocean Monument
case 5393476 -> builder.damage(4); // Woodland explorer
+ case 12741452 -> builder.damage(14); // Trial Chamber
}
}
}
diff --git a/core/src/main/java/org/geysermc/geyser/item/type/FireworkRocketItem.java b/core/src/main/java/org/geysermc/geyser/item/type/FireworkRocketItem.java
index c70467b4c..9c637afde 100644
--- a/core/src/main/java/org/geysermc/geyser/item/type/FireworkRocketItem.java
+++ b/core/src/main/java/org/geysermc/geyser/item/type/FireworkRocketItem.java
@@ -70,8 +70,8 @@ public class FireworkRocketItem extends Item {
}
@Override
- public void translateNbtToJava(@NonNull NbtMap bedrockTag, @NonNull DataComponents components, @NonNull ItemMapping mapping) {
- super.translateNbtToJava(bedrockTag, components, mapping);
+ public void translateNbtToJava(@NonNull GeyserSession session, @NonNull NbtMap bedrockTag, @NonNull DataComponents components, @NonNull ItemMapping mapping) {
+ super.translateNbtToJava(session, bedrockTag, components, mapping);
NbtMap fireworksTag = bedrockTag.getCompound("Fireworks");
if (!fireworksTag.isEmpty()) {
diff --git a/core/src/main/java/org/geysermc/geyser/item/type/FireworkStarItem.java b/core/src/main/java/org/geysermc/geyser/item/type/FireworkStarItem.java
index 18234975d..5ac0f475c 100644
--- a/core/src/main/java/org/geysermc/geyser/item/type/FireworkStarItem.java
+++ b/core/src/main/java/org/geysermc/geyser/item/type/FireworkStarItem.java
@@ -78,8 +78,8 @@ public class FireworkStarItem extends Item {
}
@Override
- public void translateNbtToJava(@NonNull NbtMap bedrockTag, @NonNull DataComponents components, @NonNull ItemMapping mapping) {
- super.translateNbtToJava(bedrockTag, components, mapping);
+ public void translateNbtToJava(@NonNull GeyserSession session, @NonNull NbtMap bedrockTag, @NonNull DataComponents components, @NonNull ItemMapping mapping) {
+ super.translateNbtToJava(session, bedrockTag, components, mapping);
NbtMap explosion = bedrockTag.getCompound("FireworksItem");
if (!explosion.isEmpty()) {
@@ -90,4 +90,9 @@ public class FireworkStarItem extends Item {
components.put(DataComponentType.FIREWORK_EXPLOSION, newExplosion);
}
}
+
+ @Override
+ public boolean ignoreDamage() {
+ return true;
+ }
}
diff --git a/core/src/main/java/org/geysermc/geyser/item/type/GoatHornItem.java b/core/src/main/java/org/geysermc/geyser/item/type/GoatHornItem.java
index cd21c0b6e..d0e85ec52 100644
--- a/core/src/main/java/org/geysermc/geyser/item/type/GoatHornItem.java
+++ b/core/src/main/java/org/geysermc/geyser/item/type/GoatHornItem.java
@@ -62,4 +62,9 @@ public class GoatHornItem extends Item {
return itemStack;
}
+
+ @Override
+ public boolean ignoreDamage() {
+ return true;
+ }
}
diff --git a/core/src/main/java/org/geysermc/geyser/item/type/Item.java b/core/src/main/java/org/geysermc/geyser/item/type/Item.java
index bfcfb23d1..362b760c7 100644
--- a/core/src/main/java/org/geysermc/geyser/item/type/Item.java
+++ b/core/src/main/java/org/geysermc/geyser/item/type/Item.java
@@ -33,8 +33,10 @@ import org.cloudburstmc.nbt.NbtType;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.inventory.GeyserItemStack;
-import org.geysermc.geyser.inventory.item.Enchantment;
+import org.geysermc.geyser.inventory.item.BedrockEnchantment;
import org.geysermc.geyser.item.Items;
+import org.geysermc.geyser.item.enchantment.Enchantment;
+import org.geysermc.geyser.level.block.type.Block;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.registry.type.ItemMappings;
import org.geysermc.geyser.session.GeyserSession;
@@ -43,16 +45,19 @@ import org.geysermc.geyser.text.MinecraftLocale;
import org.geysermc.geyser.translator.item.BedrockItemBuilder;
import org.geysermc.geyser.translator.item.ItemTranslator;
import org.geysermc.geyser.translator.text.MessageTranslator;
-import org.geysermc.mcprotocollib.protocol.data.game.Identifier;
+import org.geysermc.geyser.util.MinecraftKey;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents;
+import org.geysermc.mcprotocollib.protocol.data.game.item.component.DyedItemColor;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.ItemEnchantments;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Item {
+ private static final Map BLOCK_TO_ITEM = new HashMap<>();
private final String javaIdentifier;
private int javaId = -1;
private final int stackSize;
@@ -60,7 +65,7 @@ public class Item {
private final int maxDamage;
public Item(String javaIdentifier, Builder builder) {
- this.javaIdentifier = Identifier.formalize(javaIdentifier).intern();
+ this.javaIdentifier = MinecraftKey.key(javaIdentifier).asString().intern();
this.stackSize = builder.stackSize;
this.maxDamage = builder.maxDamage;
this.attackDamage = builder.attackDamage;
@@ -120,7 +125,7 @@ public class Item {
*/
public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull BedrockItemBuilder builder) {
List loreComponents = components.get(DataComponentType.LORE);
- if (loreComponents != null) {
+ if (loreComponents != null && components.get(DataComponentType.HIDE_TOOLTIP) == null) {
List lore = builder.getOrCreateLore();
for (Component loreComponent : loreComponents) {
lore.add(MessageTranslator.convertMessage(loreComponent, session.locale()));
@@ -167,7 +172,7 @@ public class Item {
*
* Therefore, if translation cannot be achieved for a certain item, it is not necessarily bad.
*/
- public void translateNbtToJava(@NonNull NbtMap bedrockTag, @NonNull DataComponents components, @NonNull ItemMapping mapping) {
+ public void translateNbtToJava(@NonNull GeyserSession session, @NonNull NbtMap bedrockTag, @NonNull DataComponents components, @NonNull ItemMapping mapping) {
// TODO see if any items from the creative menu need this
// CompoundTag displayTag = tag.get("display");
// if (displayTag != null) {
@@ -185,68 +190,48 @@ public class Item {
// }
// displayTag.put(new ListTag("Lore", lore));
// }
-// }
-
- // TODO no creative item should have enchantments *except* enchanted books
-// List enchantmentTag = bedrockTag.getList("ench", NbtType.COMPOUND);
-// if (enchantmentTag != null) {
-// List enchantments = new ArrayList<>();
-// for (Tag value : enchantmentTag.getValue()) {
-// if (!(value instanceof CompoundTag tagValue))
-// continue;
-//
-// ShortTag bedrockId = tagValue.get("id");
-// if (bedrockId == null) continue;
-//
-// Enchantment enchantment = Enchantment.getByBedrockId(bedrockId.getValue());
-// if (enchantment != null) {
-// CompoundTag javaTag = new CompoundTag("");
-// Map javaValue = javaTag.getValue();
-// javaValue.put("id", new StringTag("id", enchantment.getJavaIdentifier()));
-// ShortTag levelTag = tagValue.get("lvl");
-// javaValue.put("lvl", new IntTag("lvl", levelTag != null ? levelTag.getValue() : 1));
-// javaTag.setValue(javaValue);
-//
-// enchantments.add(javaTag);
-// } else {
-// GeyserImpl.getInstance().getLogger().debug("Unknown bedrock enchantment: " + bedrockId);
-// }
-// }
-// if (!enchantments.isEmpty()) {
-// if ((this instanceof EnchantedBookItem)) {
-// bedrockTag.put(new ListTag("StoredEnchantments", enchantments));
-// components.put(DataComponentType.STORED_ENCHANTMENTS, enchantments);
-// } else {
-// components.put(DataComponentType.ENCHANTMENTS, enchantments);
-// }
-// }
// }
}
protected final @Nullable NbtMap remapEnchantment(GeyserSession session, int enchantId, int level, BedrockItemBuilder builder) {
- // TODO verify
- // TODO streamline Enchantment process
- Enchantment.JavaEnchantment enchantment = Enchantment.JavaEnchantment.of(enchantId);
- if (enchantment == Enchantment.JavaEnchantment.SWEEPING_EDGE) {
- addSweeping(session, builder, level);
- return null;
- }
+ Enchantment enchantment = session.getRegistryCache().enchantments().byId(enchantId);
if (enchantment == null) {
GeyserImpl.getInstance().getLogger().debug("Unknown Java enchantment while NBT item translating: " + enchantId);
return null;
}
+ BedrockEnchantment bedrockEnchantment = enchantment.bedrockEnchantment();
+ if (bedrockEnchantment == null) {
+ String enchantmentTranslation = MinecraftLocale.getLocaleString(enchantment.description(), session.locale());
+ addJavaOnlyEnchantment(session, builder, enchantmentTranslation, level);
+ return null;
+ }
+
return NbtMap.builder()
- .putShort("id", (short) Enchantment.valueOf(enchantment.name()).ordinal())
+ .putShort("id", (short) bedrockEnchantment.ordinal())
.putShort("lvl", (short) level)
.build();
}
- private void addSweeping(GeyserSession session, BedrockItemBuilder builder, int level) {
- String sweepingTranslation = MinecraftLocale.getLocaleString("enchantment.minecraft.sweeping", session.locale());
+ private void addJavaOnlyEnchantment(GeyserSession session, BedrockItemBuilder builder, String enchantmentName, int level) {
String lvlTranslation = MinecraftLocale.getLocaleString("enchantment.level." + level, session.locale());
- builder.getOrCreateLore().add(ChatColor.RESET + ChatColor.GRAY + sweepingTranslation + " " + lvlTranslation);
+ builder.getOrCreateLore().add(0, ChatColor.RESET + ChatColor.GRAY + enchantmentName + " " + lvlTranslation);
+ }
+
+ protected final void translateDyedColor(DataComponents components, BedrockItemBuilder builder) {
+ DyedItemColor dyedItemColor = components.get(DataComponentType.DYED_COLOR);
+ if (dyedItemColor != null) {
+ builder.putInt("customColor", dyedItemColor.getRgb());
+ }
+ }
+
+ /**
+ * Override if the Bedrock equivalent of an item uses damage for extra data, and should not be tracked
+ * when translating an item.
+ */
+ public boolean ignoreDamage() {
+ return false;
}
/* Translation methods end */
@@ -270,6 +255,18 @@ public class Item {
'}';
}
+ /**
+ * @return the block associated with this item, or air if nothing
+ */
+ @NonNull
+ public static Item byBlock(Block block) {
+ return BLOCK_TO_ITEM.getOrDefault(block, Items.AIR);
+ }
+
+ protected static void registerBlock(Block block, Item item) {
+ BLOCK_TO_ITEM.put(block, item);
+ }
+
public static Builder builder() {
return new Builder();
}
diff --git a/core/src/main/java/org/geysermc/geyser/item/type/OminousBottleItem.java b/core/src/main/java/org/geysermc/geyser/item/type/OminousBottleItem.java
new file mode 100644
index 000000000..815f71419
--- /dev/null
+++ b/core/src/main/java/org/geysermc/geyser/item/type/OminousBottleItem.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2024 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.item.type;
+
+import org.checkerframework.checker.nullness.qual.NonNull;
+import org.checkerframework.checker.nullness.qual.Nullable;
+import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
+import org.geysermc.geyser.inventory.GeyserItemStack;
+import org.geysermc.geyser.registry.type.ItemMapping;
+import org.geysermc.geyser.registry.type.ItemMappings;
+import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType;
+import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents;
+
+public class OminousBottleItem extends Item {
+ public OminousBottleItem(String javaIdentifier, Builder builder) {
+ super(javaIdentifier, builder);
+ }
+
+ @Override
+ public ItemData.Builder translateToBedrock(int count, @Nullable DataComponents components, ItemMapping mapping, ItemMappings mappings) {
+ var builder = super.translateToBedrock(count, components, mapping, mappings);
+ if (components == null) {
+ // Level 1 ominous bottle is null components - Java 1.21.
+ return builder;
+ }
+ Integer amplifier = components.get(DataComponentType.OMINOUS_BOTTLE_AMPLIFIER);
+ if (amplifier != null) {
+ builder.damage(amplifier);
+ }
+ return builder;
+ }
+
+ @Override
+ public @NonNull GeyserItemStack translateToJava(@NonNull ItemData itemData, @NonNull ItemMapping mapping, @NonNull ItemMappings mappings) {
+ // This item can be pulled from the creative inventory with amplifiers.
+ GeyserItemStack itemStack = super.translateToJava(itemData, mapping, mappings);
+ int damage = itemData.getDamage();
+ if (damage == 0) {
+ return itemStack;
+ }
+ itemStack.getOrCreateComponents().put(DataComponentType.OMINOUS_BOTTLE_AMPLIFIER, damage);
+ return itemStack;
+ }
+
+ @Override
+ public boolean ignoreDamage() {
+ return true;
+ }
+}
diff --git a/core/src/main/java/org/geysermc/geyser/item/type/PlayerHeadItem.java b/core/src/main/java/org/geysermc/geyser/item/type/PlayerHeadItem.java
index 0cdbe70f1..86572d60c 100644
--- a/core/src/main/java/org/geysermc/geyser/item/type/PlayerHeadItem.java
+++ b/core/src/main/java/org/geysermc/geyser/item/type/PlayerHeadItem.java
@@ -27,6 +27,7 @@ package org.geysermc.geyser.item.type;
import com.github.steveice10.mc.auth.data.GameProfile;
import org.checkerframework.checker.nullness.qual.NonNull;
+import org.geysermc.geyser.level.block.type.Block;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.text.ChatColor;
import org.geysermc.geyser.text.MinecraftLocale;
@@ -34,9 +35,9 @@ import org.geysermc.geyser.translator.item.BedrockItemBuilder;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents;
-public class PlayerHeadItem extends Item {
- public PlayerHeadItem(String javaIdentifier, Builder builder) {
- super(javaIdentifier, builder);
+public class PlayerHeadItem extends BlockItem {
+ public PlayerHeadItem(Builder builder, Block block, Block... otherBlocks) {
+ super(builder, block, otherBlocks);
}
@Override
diff --git a/core/src/main/java/org/geysermc/geyser/item/type/PotionItem.java b/core/src/main/java/org/geysermc/geyser/item/type/PotionItem.java
index e9889c882..f8fe2b4ee 100644
--- a/core/src/main/java/org/geysermc/geyser/item/type/PotionItem.java
+++ b/core/src/main/java/org/geysermc/geyser/item/type/PotionItem.java
@@ -76,4 +76,9 @@ public class PotionItem extends Item {
}
return itemStack;
}
+
+ @Override
+ public boolean ignoreDamage() {
+ return true;
+ }
}
diff --git a/core/src/main/java/org/geysermc/geyser/item/type/ShulkerBoxItem.java b/core/src/main/java/org/geysermc/geyser/item/type/ShulkerBoxItem.java
index 6b2d589d6..a539fa739 100644
--- a/core/src/main/java/org/geysermc/geyser/item/type/ShulkerBoxItem.java
+++ b/core/src/main/java/org/geysermc/geyser/item/type/ShulkerBoxItem.java
@@ -30,6 +30,7 @@ import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.nbt.NbtMapBuilder;
import org.cloudburstmc.nbt.NbtType;
import org.geysermc.geyser.item.Items;
+import org.geysermc.geyser.level.block.type.Block;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.item.BedrockItemBuilder;
@@ -42,8 +43,8 @@ import java.util.ArrayList;
import java.util.List;
public class ShulkerBoxItem extends BlockItem {
- public ShulkerBoxItem(String javaIdentifier, Builder builder) {
- super(javaIdentifier, builder);
+ public ShulkerBoxItem(Builder builder, Block block, Block... otherBlocks) {
+ super(builder, block, otherBlocks);
}
@Override
diff --git a/core/src/main/java/org/geysermc/geyser/item/type/TippedArrowItem.java b/core/src/main/java/org/geysermc/geyser/item/type/TippedArrowItem.java
index 85291886e..d9e58eaf9 100644
--- a/core/src/main/java/org/geysermc/geyser/item/type/TippedArrowItem.java
+++ b/core/src/main/java/org/geysermc/geyser/item/type/TippedArrowItem.java
@@ -27,7 +27,7 @@ package org.geysermc.geyser.item.type;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
import org.geysermc.geyser.GeyserImpl;
-import org.geysermc.geyser.inventory.item.TippedArrowPotion;
+import org.geysermc.geyser.inventory.item.Potion;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.registry.type.ItemMappings;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType;
@@ -41,16 +41,18 @@ public class TippedArrowItem extends ArrowItem {
@Override
public ItemData.Builder translateToBedrock(int count, DataComponents components, ItemMapping mapping, ItemMappings mappings) {
- PotionContents potionContents = components.get(DataComponentType.POTION_CONTENTS);
- if (potionContents != null) {
- TippedArrowPotion tippedArrowPotion = TippedArrowPotion.of(potionContents.getPotionId());
- if (tippedArrowPotion != null) {
- return ItemData.builder()
- .definition(mapping.getBedrockDefinition())
- .damage(tippedArrowPotion.getBedrockId())
- .count(count);
+ if (components != null) {
+ PotionContents potionContents = components.get(DataComponentType.POTION_CONTENTS);
+ if (potionContents != null) {
+ Potion potion = Potion.getByJavaId(potionContents.getPotionId());
+ if (potion != null) {
+ return ItemData.builder()
+ .definition(mapping.getBedrockDefinition())
+ .damage(potion.tippedArrowId())
+ .count(count);
+ }
+ GeyserImpl.getInstance().getLogger().debug("Unknown Java potion (tipped arrow): " + potionContents.getPotionId());
}
- GeyserImpl.getInstance().getLogger().debug("Unknown Java potion (tipped arrow): " + potionContents.getPotionId());
}
return super.translateToBedrock(count, components, mapping, mappings);
}
diff --git a/core/src/main/java/org/geysermc/geyser/item/type/WolfArmorItem.java b/core/src/main/java/org/geysermc/geyser/item/type/WolfArmorItem.java
new file mode 100644
index 000000000..bd97a6a7d
--- /dev/null
+++ b/core/src/main/java/org/geysermc/geyser/item/type/WolfArmorItem.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2024 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.item.type;
+
+import org.checkerframework.checker.nullness.qual.NonNull;
+import org.geysermc.geyser.item.ArmorMaterial;
+import org.geysermc.geyser.session.GeyserSession;
+import org.geysermc.geyser.translator.item.BedrockItemBuilder;
+import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents;
+
+public class WolfArmorItem extends ArmorItem {
+ public WolfArmorItem(String javaIdentifier, ArmorMaterial material, Builder builder) {
+ super(javaIdentifier, material, builder);
+ }
+
+ @Override
+ public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull BedrockItemBuilder builder) {
+ super.translateComponentsToBedrock(session, components, builder);
+
+ // Note that this is handled as of 1.21 in the ItemColors class.
+ translateDyedColor(components, builder);
+ }
+}
diff --git a/core/src/main/java/org/geysermc/geyser/level/BedrockMapIcon.java b/core/src/main/java/org/geysermc/geyser/level/BedrockMapIcon.java
index c55a74cd2..eacf6bd1b 100644
--- a/core/src/main/java/org/geysermc/geyser/level/BedrockMapIcon.java
+++ b/core/src/main/java/org/geysermc/geyser/level/BedrockMapIcon.java
@@ -63,7 +63,8 @@ public enum BedrockMapIcon {
ICON_SNOWY_VILLAGE(MapIconType.SNOWY_VILLAGE, 20),
ICON_TAIGA_VILLAGE(MapIconType.TAIGA_VILLAGE, 21),
ICON_JUNGLE_TEMPLE(MapIconType.JUNGLE_TEMPLE, 22),
- ICON_SWAMP_HUT(MapIconType.SWAMP_HUT, 23);
+ ICON_SWAMP_HUT(MapIconType.SWAMP_HUT, 23),
+ ICON_TRIAL_CHAMBERS(MapIconType.TRIAL_CHAMBERS, 24);
private static final BedrockMapIcon[] VALUES = values();
diff --git a/core/src/main/java/org/geysermc/geyser/level/GeyserWorldManager.java b/core/src/main/java/org/geysermc/geyser/level/GeyserWorldManager.java
index 08611a5e1..9faa7424c 100644
--- a/core/src/main/java/org/geysermc/geyser/level/GeyserWorldManager.java
+++ b/core/src/main/java/org/geysermc/geyser/level/GeyserWorldManager.java
@@ -25,24 +25,20 @@
package org.geysermc.geyser.level;
+import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.objects.Object2ObjectMap;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
-import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.cloudburstmc.math.vector.Vector3i;
-import org.cloudburstmc.nbt.NbtMap;
-import org.cloudburstmc.nbt.NbtMapBuilder;
-import org.geysermc.erosion.packet.backendbound.*;
+import org.geysermc.erosion.packet.backendbound.BackendboundBatchBlockRequestPacket;
+import org.geysermc.erosion.packet.backendbound.BackendboundBlockRequestPacket;
+import org.geysermc.erosion.packet.backendbound.BackendboundPickBlockPacket;
import org.geysermc.erosion.util.BlockPositionIterator;
-import org.geysermc.erosion.util.LecternUtils;
import org.geysermc.geyser.session.GeyserSession;
-import org.geysermc.geyser.util.BlockEntityUtils;
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents;
-import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityInfo;
-import java.util.List;
import java.util.concurrent.CompletableFuture;
public class GeyserWorldManager extends WorldManager {
@@ -91,51 +87,6 @@ public class GeyserWorldManager extends WorldManager {
return false;
}
- @Override
- public void sendLecternData(GeyserSession session, int x, int z, List blockEntityInfos) {
- var erosionHandler = session.getErosionHandler().getAsActive();
- if (erosionHandler == null) {
- // No-op - don't send any additional information other than what the chunk has already sent
- return;
- }
- List vectors = new ObjectArrayList<>(blockEntityInfos.size());
- //noinspection ForLoopReplaceableByForEach - avoid constructing iterator
- for (int i = 0; i < blockEntityInfos.size(); i++) {
- BlockEntityInfo info = blockEntityInfos.get(i);
- vectors.add(Vector3i.from(info.getX(), info.getY(), info.getZ()));
- }
- erosionHandler.sendPacket(new BackendboundBatchBlockEntityPacket(x, z, vectors));
- }
-
- @Override
- public void sendLecternData(GeyserSession session, int x, int y, int z) {
- var erosionHandler = session.getErosionHandler().getAsActive();
- if (erosionHandler != null) {
- erosionHandler.sendPacket(new BackendboundBlockEntityPacket(Vector3i.from(x, y, z)));
- return;
- }
-
- // Without direct server access, we can't get lectern information on-the-fly.
- // I should have set this up so it's only called when there is a book in the block state. - Camotoy
- NbtMapBuilder lecternTag = LecternUtils.getBaseLecternTag(x, y, z, 1);
- lecternTag.putCompound("book", NbtMap.builder()
- .putByte("Count", (byte) 1)
- .putShort("Damage", (short) 0)
- .putString("Name", "minecraft:written_book")
- .putCompound("tag", NbtMap.builder()
- .putString("photoname", "")
- .putString("text", "")
- .build())
- .build());
- lecternTag.putInt("page", -1); // I'm surprisingly glad this exists - it forces Bedrock to stop reading immediately. Usually.
- BlockEntityUtils.updateBlockEntity(session, lecternTag.build(), Vector3i.from(x, y, z));
- }
-
- @Override
- public boolean shouldExpectLecternHandled(GeyserSession session) {
- return session.getErosionHandler().isActive();
- }
-
@Override
public void setGameRule(GeyserSession session, String name, Object value) {
super.setGameRule(session, name, value);
@@ -179,9 +130,9 @@ public class GeyserWorldManager extends WorldManager {
if (erosionHandler == null) {
return super.getPickItemComponents(session, x, y, z, addNbtData);
}
- CompletableFuture future = new CompletableFuture<>();
+ CompletableFuture> future = new CompletableFuture<>();
erosionHandler.setPickBlockLookup(future);
erosionHandler.sendPacket(new BackendboundPickBlockPacket(Vector3i.from(x, y, z)));
- return future;
+ return future.thenApply(RAW_TRANSFORMER);
}
}
diff --git a/core/src/main/java/org/geysermc/geyser/level/JukeboxSong.java b/core/src/main/java/org/geysermc/geyser/level/JukeboxSong.java
new file mode 100644
index 000000000..156a62cd1
--- /dev/null
+++ b/core/src/main/java/org/geysermc/geyser/level/JukeboxSong.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2024 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.level;
+
+import org.cloudburstmc.nbt.NbtMap;
+import org.geysermc.geyser.GeyserImpl;
+import org.geysermc.geyser.translator.text.MessageTranslator;
+import org.geysermc.mcprotocollib.protocol.data.game.RegistryEntry;
+
+public record JukeboxSong(String soundEvent, String description) {
+
+ public static JukeboxSong read(RegistryEntry entry) {
+ NbtMap data = entry.getData();
+ Object soundEventObject = data.get("sound_event");
+ String soundEvent;
+ if (soundEventObject instanceof NbtMap map) {
+ soundEvent = map.getString("sound_id");
+ } else if (soundEventObject instanceof String string) {
+ soundEvent = string;
+ } else {
+ soundEvent = "";
+ GeyserImpl.getInstance().getLogger().debug("Sound event for " + entry.getId() + " was of an unexpected type! Expected string or NBT map, got " + soundEventObject);
+ }
+ String description = MessageTranslator.deserializeDescription(data);
+ return new JukeboxSong(soundEvent, description);
+ }
+}
diff --git a/core/src/main/java/org/geysermc/geyser/level/PaintingType.java b/core/src/main/java/org/geysermc/geyser/level/PaintingType.java
index 643fd735d..f829b481c 100644
--- a/core/src/main/java/org/geysermc/geyser/level/PaintingType.java
+++ b/core/src/main/java/org/geysermc/geyser/level/PaintingType.java
@@ -28,6 +28,9 @@ package org.geysermc.geyser.level;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
+import net.kyori.adventure.key.Key;
+
+import java.util.Locale;
@AllArgsConstructor(access = AccessLevel.PRIVATE)
@Getter
@@ -61,21 +64,40 @@ public enum PaintingType {
EARTH("Earth", 2, 2),
WIND("Wind", 2, 2),
WATER("Water", 2, 2),
- FIRE("Fire", 2, 2);
+ FIRE("Fire", 2, 2),
+ MEDITATIVE("meditative", 1, 1),
+ PRAIRIE_RIDE("prairie_ride", 1, 2),
+ BAROQUE("baroque", 2, 2),
+ HUMBLE("humble", 2, 2),
+ UNPACKED("unpacked", 4, 4),
+ BACKYARD("backyard", 3, 4),
+ BOUQUET("bouquet", 3, 3),
+ CAVEBIRD("cavebird", 3, 3),
+ CHANGING("changing", 4, 2),
+ COTAN("cotan", 3, 3),
+ ENDBOSS("endboss", 3, 3),
+ FERN("fern", 3, 3),
+ FINDING("finding", 4, 2),
+ LOWMIST("lowmist", 4, 2),
+ ORB("orb", 4, 4),
+ OWLEMONS("owlemons", 3, 3),
+ PASSAGE("passage", 4, 2),
+ POND("pond", 3, 4),
+ SUNFLOWERS("sunflowers", 3, 3),
+ TIDES("tides", 3, 3);
private static final PaintingType[] VALUES = values();
private final String bedrockName;
private final int width;
private final int height;
- public static PaintingType getByName(String javaName) {
- for (PaintingType paintingName : VALUES) {
- if (paintingName.name().equalsIgnoreCase(javaName)) return paintingName;
+ public static PaintingType getByName(Key key) {
+ if (!key.namespace().equals("minecraft")) {
+ return null;
}
- return KEBAB;
- }
-
- public static PaintingType getByPaintingType(org.geysermc.mcprotocollib.protocol.data.game.entity.type.PaintingType paintingType) {
- return getByName(paintingType.name());
+ for (PaintingType paintingName : VALUES) {
+ if (paintingName.name().toLowerCase(Locale.ROOT).equals(key.value())) return paintingName;
+ }
+ return null;
}
}
diff --git a/core/src/main/java/org/geysermc/geyser/level/WorldManager.java b/core/src/main/java/org/geysermc/geyser/level/WorldManager.java
index a1b16a1d5..4a20771f2 100644
--- a/core/src/main/java/org/geysermc/geyser/level/WorldManager.java
+++ b/core/src/main/java/org/geysermc/geyser/level/WorldManager.java
@@ -25,19 +25,30 @@
package org.geysermc.geyser.level;
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
+import it.unimi.dsi.fastutil.ints.Int2ObjectMaps;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.cloudburstmc.math.vector.Vector3i;
import org.geysermc.erosion.util.BlockPositionIterator;
+import org.geysermc.geyser.level.block.type.BlockState;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode;
+import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponent;
+import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents;
-import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityInfo;
+import org.geysermc.mcprotocollib.protocol.data.game.item.component.ItemCodecHelper;
import org.geysermc.mcprotocollib.protocol.data.game.setting.Difficulty;
+import java.util.HashMap;
import java.util.List;
import java.util.Locale;
+import java.util.Map;
import java.util.concurrent.CompletableFuture;
+import java.util.function.Consumer;
+import java.util.function.Function;
/**
* Class that manages or retrieves various information
@@ -48,6 +59,16 @@ import java.util.concurrent.CompletableFuture;
*/
public abstract class WorldManager {
+ @NonNull
+ public final BlockState blockAt(GeyserSession session, Vector3i vector) {
+ return this.blockAt(session, vector.getX(), vector.getY(), vector.getZ());
+ }
+
+ @NonNull
+ public BlockState blockAt(GeyserSession session, int x, int y, int z) {
+ return BlockState.of(this.getBlockAt(session, x, y, z));
+ }
+
/**
* Gets the Java block state at the specified location
*
@@ -97,40 +118,6 @@ public abstract class WorldManager {
*/
public abstract boolean hasOwnChunkCache();
- /**
- * Sigh.
- *
- * So, on Java Edition, the lectern is an inventory. Java opens it and gets the contents of the book there.
- * On Bedrock, the lectern contents are part of the block entity tag. Therefore, Bedrock expects to have the contents
- * of the lectern ready and present in the world. If the contents are not there, it takes at least two clicks for the
- * lectern to update the tag and then present itself.
- *
- * We solve this problem by querying all loaded lecterns, where possible, and sending their information in a block entity
- * tag.
- *
- * Note that the lectern data may be sent asynchronously.
- *
- * @param session the session of the player
- * @param x the x coordinate of the lectern
- * @param y the y coordinate of the lectern
- * @param z the z coordinate of the lectern
- */
- public abstract void sendLecternData(GeyserSession session, int x, int y, int z);
-
- /**
- * {@link #sendLecternData(GeyserSession, int, int, int)} but batched for chunks.
- *
- * @param x chunk x
- * @param z chunk z
- * @param blockEntityInfos a list of coordinates (chunk local) to grab lecterns from.
- */
- public abstract void sendLecternData(GeyserSession session, int x, int z, List blockEntityInfos);
-
- /**
- * @return whether we should expect lectern data to update, or if we have to fall back on a workaround.
- */
- public abstract boolean shouldExpectLecternHandled(GeyserSession session);
-
/**
* Updates a gamerule value on the Java server
*
@@ -223,4 +210,27 @@ public abstract class WorldManager {
public CompletableFuture<@Nullable DataComponents> getPickItemComponents(GeyserSession session, int x, int y, int z, boolean addExtraData) {
return CompletableFuture.completedFuture(null);
}
+
+ /**
+ * Retrieves decorated pot sherds from the server. Used to ensure the data is not erased on animation sent
+ * through the BlockEntityDataPacket.
+ */
+ public void getDecoratedPotData(GeyserSession session, Vector3i pos, Consumer> apply) {
+ }
+
+ protected static final Function, DataComponents> RAW_TRANSFORMER = map -> {
+ try {
+ Map, DataComponent, ?>> components = new HashMap<>();
+ Int2ObjectMaps.fastForEach(map, entry -> {
+ DataComponentType type = DataComponentType.from(entry.getIntKey());
+ ByteBuf buf = Unpooled.wrappedBuffer(entry.getValue());
+ DataComponent value = type.readDataComponent(ItemCodecHelper.INSTANCE, buf);
+ components.put(type, value);
+ });
+ return new DataComponents(components);
+ } catch (Exception e) {
+ e.printStackTrace();
+ return null;
+ }
+ };
}
diff --git a/core/src/main/java/org/geysermc/geyser/level/block/BlockStateValues.java b/core/src/main/java/org/geysermc/geyser/level/block/BlockStateValues.java
index 52759c709..01e95fc7a 100644
--- a/core/src/main/java/org/geysermc/geyser/level/block/BlockStateValues.java
+++ b/core/src/main/java/org/geysermc/geyser/level/block/BlockStateValues.java
@@ -25,363 +25,19 @@
package org.geysermc.geyser.level.block;
-import com.fasterxml.jackson.databind.JsonNode;
-import it.unimi.dsi.fastutil.ints.*;
-import it.unimi.dsi.fastutil.objects.Object2IntMap;
-import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
-import org.geysermc.geyser.level.physics.Direction;
+import org.geysermc.geyser.level.block.property.Properties;
+import org.geysermc.geyser.level.block.type.Block;
+import org.geysermc.geyser.level.block.type.BlockState;
+import org.geysermc.geyser.level.block.type.PistonBlock;
import org.geysermc.geyser.level.physics.PistonBehavior;
import org.geysermc.geyser.registry.BlockRegistries;
-import org.geysermc.geyser.registry.type.BlockMapping;
-import org.geysermc.geyser.translator.level.block.entity.PistonBlockEntityTranslator;
-import org.geysermc.geyser.util.collection.FixedInt2ByteMap;
-import org.geysermc.geyser.util.collection.FixedInt2IntMap;
-import org.geysermc.geyser.util.collection.LecternHasBookMap;
-
-import java.util.Locale;
/**
* Used for block entities if the Java block state contains Bedrock block information.
*/
public final class BlockStateValues {
- private static final IntSet ALL_CAULDRONS = new IntOpenHashSet();
- private static final Int2IntMap BANNER_COLORS = new FixedInt2IntMap();
- private static final Int2ByteMap BED_COLORS = new FixedInt2ByteMap();
- private static final Int2IntMap BRUSH_PROGRESS = new Int2IntOpenHashMap();
- private static final Int2ByteMap COMMAND_BLOCK_VALUES = new Int2ByteOpenHashMap();
- private static final Int2ObjectMap DOUBLE_CHEST_VALUES = new Int2ObjectOpenHashMap<>();
- private static final Int2ObjectMap FLOWER_POT_VALUES = new Int2ObjectOpenHashMap<>();
- private static final IntSet HORIZONTAL_FACING_JIGSAWS = new IntOpenHashSet();
- private static final LecternHasBookMap LECTERN_BOOK_STATES = new LecternHasBookMap();
- private static final IntSet NON_WATER_CAULDRONS = new IntOpenHashSet();
- private static final Int2IntMap NOTEBLOCK_PITCHES = new FixedInt2IntMap();
- private static final Int2BooleanMap PISTON_VALUES = new Int2BooleanOpenHashMap();
- private static final IntSet STICKY_PISTONS = new IntOpenHashSet();
- private static final Object2IntMap PISTON_HEADS = new Object2IntOpenHashMap<>();
- private static final Int2ObjectMap PISTON_ORIENTATION = new Int2ObjectOpenHashMap<>();
- private static final IntSet ALL_PISTON_HEADS = new IntOpenHashSet();
- private static final IntSet MOVING_PISTONS = new IntOpenHashSet();
- private static final Int2ByteMap SKULL_VARIANTS = new FixedInt2ByteMap();
- private static final IntSet SKULL_POWERED = new IntOpenHashSet();
- private static final Int2ByteMap SKULL_ROTATIONS = new Int2ByteOpenHashMap();
- private static final Int2IntMap SKULL_WALL_DIRECTIONS = new Int2IntOpenHashMap();
- private static final Int2ByteMap SHULKERBOX_DIRECTIONS = new FixedInt2ByteMap();
- private static final Int2IntMap WATER_LEVEL = new Int2IntOpenHashMap();
- private static final IntSet UPPER_DOORS = new IntOpenHashSet();
-
- public static final int JAVA_AIR_ID = 0;
-
- public static int JAVA_COBWEB_ID;
- public static int JAVA_FURNACE_ID;
- public static int JAVA_FURNACE_LIT_ID;
- public static int JAVA_HONEY_BLOCK_ID;
- public static int JAVA_SLIME_BLOCK_ID;
- public static int JAVA_SPAWNER_ID;
- public static int JAVA_WATER_ID;
-
public static final int NUM_WATER_LEVELS = 9;
- /**
- * Determines if the block state contains Bedrock block information
- *
- * @param javaId The Java Identifier of the block
- * @param javaBlockState the Java Block State of the block
- * @param blockData JsonNode of info about the block from blocks.json
- */
- public static void storeBlockStateValues(String javaId, int javaBlockState, JsonNode blockData) {
- JsonNode bannerColor = blockData.get("banner_color");
- if (bannerColor != null) {
- BANNER_COLORS.put(javaBlockState, (byte) bannerColor.intValue());
- return; // There will never be a banner color and a skull variant
- }
-
- JsonNode bedColor = blockData.get("bed_color");
- if (bedColor != null) {
- BED_COLORS.put(javaBlockState, (byte) bedColor.intValue());
- return;
- }
-
- JsonNode bedrockStates = blockData.get("bedrock_states");
- if (bedrockStates != null) {
- JsonNode brushedProgress = bedrockStates.get("brushed_progress");
- if (brushedProgress != null) {
- BRUSH_PROGRESS.put(javaBlockState, brushedProgress.intValue());
- return;
- }
- }
-
- if (javaId.contains("command_block")) {
- COMMAND_BLOCK_VALUES.put(javaBlockState, javaId.contains("conditional=true") ? (byte) 1 : (byte) 0);
- return;
- }
-
- if (blockData.get("double_chest_position") != null) {
- boolean isX = (blockData.get("x") != null);
- boolean isDirectionPositive = ((blockData.get("x") != null && blockData.get("x").asBoolean()) ||
- (blockData.get("z") != null && blockData.get("z").asBoolean()));
- boolean isLeft = (blockData.get("double_chest_position").asText().contains("left"));
- DOUBLE_CHEST_VALUES.put(javaBlockState, new DoubleChestValue(isX, isDirectionPositive, isLeft));
- return;
- }
-
- if (javaId.startsWith("minecraft:potted_") || javaId.equals("minecraft:flower_pot")) {
- String name = javaId.replace("potted_", "");
- if (name.contains("azalea")) {
- // Exception to the rule
- name = name.replace("_bush", "");
- }
- FLOWER_POT_VALUES.put(javaBlockState, name);
- return;
- }
-
- if (javaId.startsWith("minecraft:lectern")) {
- LECTERN_BOOK_STATES.put(javaBlockState, javaId.contains("has_book=true"));
- return;
- }
-
- JsonNode notePitch = blockData.get("note_pitch");
- if (notePitch != null) {
- NOTEBLOCK_PITCHES.put(javaBlockState, blockData.get("note_pitch").intValue());
- return;
- }
-
- if (javaId.contains("piston[")) { // minecraft:moving_piston, minecraft:sticky_piston, minecraft:piston
- if (javaId.startsWith("minecraft:moving_piston")) {
- MOVING_PISTONS.add(javaBlockState);
- } else {
- PISTON_VALUES.put(javaBlockState, javaId.contains("extended=true"));
- }
- if (javaId.contains("sticky")) {
- STICKY_PISTONS.add(javaBlockState);
- }
- PISTON_ORIENTATION.put(javaBlockState, getBlockDirection(javaId));
- return;
- } else if (javaId.startsWith("minecraft:piston_head")) {
- ALL_PISTON_HEADS.add(javaBlockState);
- if (javaId.contains("short=false")) {
- PISTON_HEADS.put(getBlockDirection(javaId), javaBlockState);
- }
- return;
- }
-
- JsonNode skullVariation = blockData.get("variation");
- if (skullVariation != null) {
- SKULL_VARIANTS.put(javaBlockState, (byte) skullVariation.intValue());
- }
-
- JsonNode skullRotation = blockData.get("skull_rotation");
- if (skullRotation != null) {
- SKULL_ROTATIONS.put(javaBlockState, (byte) skullRotation.intValue());
- }
-
- if (javaId.startsWith("minecraft:dragon_head[") || javaId.startsWith("minecraft:piglin_head[")
- || javaId.startsWith("minecraft:dragon_wall_head[") || javaId.startsWith("minecraft:piglin_wall_head[")) {
- if (javaId.contains("powered=true")) {
- SKULL_POWERED.add(javaBlockState);
- }
- }
-
- if (javaId.contains("wall_skull") || javaId.contains("wall_head")) {
- String direction = javaId.substring(javaId.lastIndexOf("facing=") + 7, javaId.lastIndexOf("powered=") - 1);
- int rotation = switch (direction) {
- case "north" -> 180;
- case "west" -> 90;
- case "east" -> 270;
- default -> 0; // Also south
- };
- SKULL_WALL_DIRECTIONS.put(javaBlockState, rotation);
- }
-
- JsonNode shulkerDirection = blockData.get("shulker_direction");
- if (shulkerDirection != null) {
- BlockStateValues.SHULKERBOX_DIRECTIONS.put(javaBlockState, (byte) shulkerDirection.intValue());
- return;
- }
-
- if (javaId.startsWith("minecraft:water") && !javaId.contains("cauldron")) {
- String strLevel = javaId.substring(javaId.lastIndexOf("level=") + 6, javaId.length() - 1);
- int level = Integer.parseInt(strLevel);
- WATER_LEVEL.put(javaBlockState, level);
- return;
- }
-
- if (javaId.startsWith("minecraft:jigsaw[orientation=")) {
- String blockStateData = javaId.substring(javaId.indexOf("orientation=") + "orientation=".length(), javaId.lastIndexOf('_'));
- Direction direction = Direction.valueOf(blockStateData.toUpperCase(Locale.ROOT));
- if (direction.isHorizontal()) {
- HORIZONTAL_FACING_JIGSAWS.add(javaBlockState);
- }
- return;
- }
-
- if (javaId.contains("cauldron")) {
- ALL_CAULDRONS.add(javaBlockState);
- }
- if (javaId.contains("_cauldron") && !javaId.contains("water_")) {
- NON_WATER_CAULDRONS.add(javaBlockState);
- }
-
- if (javaId.contains("_door[") && javaId.contains("half=upper")) {
- UPPER_DOORS.add(javaBlockState);
- }
- }
-
- /**
- * Banner colors are part of the namespaced ID in Java Edition, but part of the block entity tag in Bedrock.
- * This gives an integer color that Bedrock can use.
- *
- * @param state BlockState of the block
- * @return Banner color integer or -1 if no color
- */
- public static int getBannerColor(int state) {
- return BANNER_COLORS.getOrDefault(state, -1);
- }
-
- /**
- * Bed colors are part of the namespaced ID in Java Edition, but part of the block entity tag in Bedrock.
- * This gives a byte color that Bedrock can use - Bedrock needs a byte in the final tag.
- *
- * @param state BlockState of the block
- * @return Bed color byte or -1 if no color
- */
- public static byte getBedColor(int state) {
- return BED_COLORS.getOrDefault(state, (byte) -1);
- }
-
- /**
- * The brush progress of suspicious sand/gravel is not sent by the java server when it updates the block entity.
- * Although brush progress is part of the bedrock block state, it must be included in the block entity update.
- *
- * @param state BlockState of the block
- * @return brush progress or 0 if the lookup failed
- */
- public static int getBrushProgress(int state) {
- return BRUSH_PROGRESS.getOrDefault(state, 0);
- }
-
- /**
- * @return if this Java block state is a non-empty non-water cauldron
- */
- public static boolean isNonWaterCauldron(int state) {
- return NON_WATER_CAULDRONS.contains(state);
- }
-
- /**
- * Cauldrons (since Bedrock 1.18.30) must have a block entity packet sent on chunk load to fix rendering issues.
- *
- * When using a bucket on a cauldron sending a ServerboundUseItemPacket can result in the liquid being placed.
- *
- * @return if this Java block state is a cauldron
- */
- public static boolean isCauldron(int state) {
- return ALL_CAULDRONS.contains(state);
- }
-
- /**
- * The block state in Java and Bedrock both contain the conditional bit, however command block block entity tags
- * in Bedrock need the conditional information.
- *
- * @return the list of all command blocks and if they are conditional (1 or 0)
- */
- public static Int2ByteMap getCommandBlockValues() {
- return COMMAND_BLOCK_VALUES;
- }
-
- /**
- * All double chest values are part of the block state in Java and part of the block entity tag in Bedrock.
- * This gives the DoubleChestValue that can be calculated into the final tag.
- *
- * @return The map of all DoubleChestValues.
- */
- public static Int2ObjectMap getDoubleChestValues() {
- return DOUBLE_CHEST_VALUES;
- }
-
- /**
- * Get the Int2ObjectMap of flower pot block states to containing plant
- *
- * @return Int2ObjectMap of flower pot values
- */
- public static Int2ObjectMap getFlowerPotValues() {
- return FLOWER_POT_VALUES;
- }
-
- /**
- * @return a set of all forward-facing jigsaws, to use as a fallback if NBT is missing.
- */
- public static IntSet getHorizontalFacingJigsaws() {
- return HORIZONTAL_FACING_JIGSAWS;
- }
-
- /**
- * @return the lectern book state map pointing to book present state
- */
- public static LecternHasBookMap getLecternBookStates() {
- return LECTERN_BOOK_STATES;
- }
-
- /**
- * The note that noteblocks output when hit is part of the block state in Java but sent as a BlockEventPacket in Bedrock.
- * This gives an integer pitch that Bedrock can use.
- *
- * @param state BlockState of the block
- * @return note block note integer or -1 if not present
- */
- public static int getNoteblockPitch(int state) {
- return NOTEBLOCK_PITCHES.getOrDefault(state, -1);
- }
-
- /**
- * Get the Int2BooleanMap showing if a piston block state is extended or not.
- *
- * @return the Int2BooleanMap of piston extensions.
- */
- public static Int2BooleanMap getPistonValues() {
- return PISTON_VALUES;
- }
-
- public static boolean isStickyPiston(int blockState) {
- return STICKY_PISTONS.contains(blockState);
- }
-
- public static boolean isPistonHead(int state) {
- return ALL_PISTON_HEADS.contains(state);
- }
-
- /**
- * Get the Java Block State for a piston head for a specific direction
- * This is used in PistonBlockEntity to get the BlockCollision for the piston head.
- *
- * @param direction Direction the piston head points in
- * @return Block state for the piston head
- */
- public static int getPistonHead(Direction direction) {
- return PISTON_HEADS.getOrDefault(direction, BlockStateValues.JAVA_AIR_ID);
- }
-
- /**
- * Check if a block is a minecraft:moving_piston
- * This is used in ChunkUtils to prevent them from being placed as it causes
- * pistons to flicker and it is not needed
- *
- * @param state Block state of the block
- * @return True if the block is a moving_piston
- */
- public static boolean isMovingPiston(int state) {
- return MOVING_PISTONS.contains(state);
- }
-
- /**
- * This is used in GeyserPistonEvents.java and accepts minecraft:piston,
- * minecraft:sticky_piston, and minecraft:moving_piston.
- *
- * @param state The block state of the piston base
- * @return The direction in which the piston faces
- */
- public static Direction getPistonOrientation(int state) {
- return PISTON_ORIENTATION.get(state);
- }
-
/**
* Checks if a block sticks to other blocks
* (Slime and honey blocks)
@@ -389,8 +45,9 @@ public final class BlockStateValues {
* @param state The block state
* @return True if the block sticks to adjacent blocks
*/
- public static boolean isBlockSticky(int state) {
- return state == JAVA_SLIME_BLOCK_ID || state == JAVA_HONEY_BLOCK_ID;
+ public static boolean isBlockSticky(BlockState state) {
+ Block block = state.block();
+ return block == Blocks.SLIME_BLOCK || block == Blocks.HONEY_BLOCK;
}
/**
@@ -400,13 +57,13 @@ public final class BlockStateValues {
* @param stateB The block state of block b
* @return True if the blocks are attached to each other
*/
- public static boolean isBlockAttached(int stateA, int stateB) {
+ public static boolean isBlockAttached(BlockState stateA, BlockState stateB) {
boolean aSticky = isBlockSticky(stateA);
boolean bSticky = isBlockSticky(stateB);
if (aSticky && bSticky) {
// Only matching sticky blocks are attached together
// Honey + Honey & Slime + Slime
- return stateA == stateB;
+ return stateA.block() == stateB.block();
}
return aSticky || bSticky;
}
@@ -415,84 +72,33 @@ public final class BlockStateValues {
* @param state The block state of the block
* @return true if a piston can break the block
*/
- public static boolean canPistonDestroyBlock(int state) {
- return BlockRegistries.JAVA_BLOCKS.getOrDefault(state, BlockMapping.DEFAULT).getPistonBehavior() == PistonBehavior.DESTROY;
+ public static boolean canPistonDestroyBlock(BlockState state) {
+ return state.block().pushReaction() == PistonBehavior.DESTROY;
}
- public static boolean canPistonMoveBlock(int javaId, boolean isPushing) {
- if (javaId == JAVA_AIR_ID) {
+ public static boolean canPistonMoveBlock(BlockState state, boolean isPushing) {
+ Block block = state.block();
+ if (block == Blocks.AIR) {
return true;
}
- // Pistons can only be moved if they aren't extended
- if (PistonBlockEntityTranslator.isBlock(javaId)) {
- return !PISTON_VALUES.get(javaId);
- }
- BlockMapping block = BlockRegistries.JAVA_BLOCKS.getOrDefault(javaId, BlockMapping.DEFAULT);
- // Bedrock, End portal frames, etc. can't be moved
- if (block.getHardness() == -1.0d) {
+ if (block == Blocks.OBSIDIAN || block == Blocks.CRYING_OBSIDIAN || block == Blocks.RESPAWN_ANCHOR || block == Blocks.REINFORCED_DEEPSLATE) { // Hardcoded as of 1.20.5
return false;
}
- return switch (block.getPistonBehavior()) {
+ // Pistons can only be moved if they aren't extended
+ if (block instanceof PistonBlock) {
+ return !state.getValue(Properties.EXTENDED);
+ }
+ // Bedrock, End portal frames, etc. can't be moved
+ if (block.destroyTime() == -1.0f) {
+ return false;
+ }
+ return switch (block.pushReaction()) {
case BLOCK, DESTROY -> false;
case PUSH_ONLY -> isPushing; // Glazed terracotta can only be pushed
- default -> !block.isBlockEntity(); // Pistons can't move block entities
+ default -> !block.hasBlockEntity(); // Pistons can't move block entities
};
}
- /**
- * Skull variations are part of the namespaced ID in Java Edition, but part of the block entity tag in Bedrock.
- * This gives a byte variant ID that Bedrock can use.
- *
- * @param state BlockState of the block
- * @return Skull variant byte or -1 if no variant
- */
- public static byte getSkullVariant(int state) {
- return SKULL_VARIANTS.getOrDefault(state, (byte) -1);
- }
-
- /**
- * Skull rotations are part of the namespaced ID in Java Edition, but part of the block entity tag in Bedrock.
- * This gives a byte rotation that Bedrock can use.
- *
- * @param state BlockState of the block
- * @return Skull rotation value or -1 if no value
- */
- public static byte getSkullRotation(int state) {
- return SKULL_ROTATIONS.getOrDefault(state, (byte) -1);
- }
-
- /**
- * As of Java 1.20.2:
- * Skull powered states are part of the namespaced ID in Java Edition, but part of the block entity tag in Bedrock.
- *
- * @param state BlockState of the block
- * @return true if this skull is currently being powered.
- */
- public static boolean isSkullPowered(int state) {
- return SKULL_POWERED.contains(state);
- }
-
- /**
- * Skull rotations are part of the namespaced ID in Java Edition, but part of the block entity tag in Bedrock.
- * This gives a integer rotation that Bedrock can use.
- *
- * @return Skull wall rotation value with the blockstate
- */
- public static Int2IntMap getSkullWallDirections() {
- return SKULL_WALL_DIRECTIONS;
- }
-
- /**
- * Shulker box directions are part of the namespaced ID in Java Edition, but part of the block entity tag in Bedrock.
- * This gives a byte direction that Bedrock can use.
- *
- * @param state BlockState of the block
- * @return Shulker direction value or -1 if no value
- */
- public static byte getShulkerBoxDirection(int state) {
- return SHULKERBOX_DIRECTIONS.getOrDefault(state, (byte) -1);
- }
-
/**
* Get the level of water from the block state.
*
@@ -500,17 +106,11 @@ public final class BlockStateValues {
* @return The water level or -1 if the block isn't water
*/
public static int getWaterLevel(int state) {
- return WATER_LEVEL.getOrDefault(state, -1);
- }
-
- /**
- * Check if a block is the upper half of a door.
- *
- * @param state BlockState of the block
- * @return True if the block is the upper half of a door
- */
- public static boolean isUpperDoor(int state) {
- return UPPER_DOORS.contains(state);
+ BlockState blockState = BlockState.of(state);
+ if (!blockState.is(Blocks.WATER)) {
+ return -1;
+ }
+ return blockState.getValue(Properties.LEVEL);
}
/**
@@ -544,31 +144,18 @@ public final class BlockStateValues {
* @param state BlockState of the block
* @return The block's slipperiness
*/
- public static float getSlipperiness(int state) {
- String blockIdentifier = BlockRegistries.JAVA_BLOCKS.getOrDefault(state, BlockMapping.DEFAULT).getJavaIdentifier();
- return switch (blockIdentifier) {
- case "minecraft:slime_block" -> 0.8f;
- case "minecraft:ice", "minecraft:packed_ice" -> 0.98f;
- case "minecraft:blue_ice" -> 0.989f;
- default -> 0.6f;
- };
- }
-
- private static Direction getBlockDirection(String javaId) {
- if (javaId.contains("down")) {
- return Direction.DOWN;
- } else if (javaId.contains("up")) {
- return Direction.UP;
- } else if (javaId.contains("south")) {
- return Direction.SOUTH;
- } else if (javaId.contains("west")) {
- return Direction.WEST;
- } else if (javaId.contains("north")) {
- return Direction.NORTH;
- } else if (javaId.contains("east")) {
- return Direction.EAST;
+ public static float getSlipperiness(BlockState state) {
+ Block block = state.block();
+ if (block == Blocks.SLIME_BLOCK) {
+ return 0.8f;
}
- throw new IllegalStateException();
+ if (block == Blocks.ICE || block == Blocks.PACKED_ICE) {
+ return 0.98f;
+ }
+ if (block == Blocks.BLUE_ICE) {
+ return 0.989f;
+ }
+ return 0.6f;
}
private BlockStateValues() {
diff --git a/core/src/main/java/org/geysermc/geyser/level/block/Blocks.java b/core/src/main/java/org/geysermc/geyser/level/block/Blocks.java
new file mode 100644
index 000000000..735c1f6c4
--- /dev/null
+++ b/core/src/main/java/org/geysermc/geyser/level/block/Blocks.java
@@ -0,0 +1,2824 @@
+/*
+ * Copyright (c) 2024 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.level.block;
+
+import org.geysermc.geyser.item.Items;
+import org.geysermc.geyser.level.block.property.ChestType;
+import org.geysermc.geyser.level.block.property.FrontAndTop;
+import org.geysermc.geyser.level.block.type.*;
+import org.geysermc.geyser.level.physics.Axis;
+import org.geysermc.geyser.level.physics.Direction;
+import org.geysermc.geyser.level.physics.PistonBehavior;
+import org.geysermc.geyser.registry.BlockRegistries;
+import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType;
+
+import static org.geysermc.geyser.level.block.property.Properties.*;
+import static org.geysermc.geyser.level.block.type.Block.builder;
+
+@SuppressWarnings("unused")
+public final class Blocks {
+ public static final Block AIR = register(new Block("air", builder()));
+ public static final Block STONE = register(new Block("stone", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
+ public static final Block GRANITE = register(new Block("granite", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
+ public static final Block POLISHED_GRANITE = register(new Block("polished_granite", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
+ public static final Block DIORITE = register(new Block("diorite", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
+ public static final Block POLISHED_DIORITE = register(new Block("polished_diorite", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
+ public static final Block ANDESITE = register(new Block("andesite", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
+ public static final Block POLISHED_ANDESITE = register(new Block("polished_andesite", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
+ public static final Block GRASS_BLOCK = register(new Block("grass_block", builder().destroyTime(0.6f)
+ .booleanState(SNOWY)));
+ public static final Block DIRT = register(new Block("dirt", builder().destroyTime(0.5f)));
+ public static final Block COARSE_DIRT = register(new Block("coarse_dirt", builder().destroyTime(0.5f)));
+ public static final Block PODZOL = register(new Block("podzol", builder().destroyTime(0.5f)
+ .booleanState(SNOWY)));
+ public static final Block COBBLESTONE = register(new Block("cobblestone", builder().requiresCorrectToolForDrops().destroyTime(2.0f)));
+ public static final Block OAK_PLANKS = register(new Block("oak_planks", builder().destroyTime(2.0f)));
+ public static final Block SPRUCE_PLANKS = register(new Block("spruce_planks", builder().destroyTime(2.0f)));
+ public static final Block BIRCH_PLANKS = register(new Block("birch_planks", builder().destroyTime(2.0f)));
+ public static final Block JUNGLE_PLANKS = register(new Block("jungle_planks", builder().destroyTime(2.0f)));
+ public static final Block ACACIA_PLANKS = register(new Block("acacia_planks", builder().destroyTime(2.0f)));
+ public static final Block CHERRY_PLANKS = register(new Block("cherry_planks", builder().destroyTime(2.0f)));
+ public static final Block DARK_OAK_PLANKS = register(new Block("dark_oak_planks", builder().destroyTime(2.0f)));
+ public static final Block MANGROVE_PLANKS = register(new Block("mangrove_planks", builder().destroyTime(2.0f)));
+ public static final Block BAMBOO_PLANKS = register(new Block("bamboo_planks", builder().destroyTime(2.0f)));
+ public static final Block BAMBOO_MOSAIC = register(new Block("bamboo_mosaic", builder().destroyTime(2.0f)));
+ public static final Block OAK_SAPLING = register(new Block("oak_sapling", builder().pushReaction(PistonBehavior.DESTROY)
+ .intState(STAGE)));
+ public static final Block SPRUCE_SAPLING = register(new Block("spruce_sapling", builder().pushReaction(PistonBehavior.DESTROY)
+ .intState(STAGE)));
+ public static final Block BIRCH_SAPLING = register(new Block("birch_sapling", builder().pushReaction(PistonBehavior.DESTROY)
+ .intState(STAGE)));
+ public static final Block JUNGLE_SAPLING = register(new Block("jungle_sapling", builder().pushReaction(PistonBehavior.DESTROY)
+ .intState(STAGE)));
+ public static final Block ACACIA_SAPLING = register(new Block("acacia_sapling", builder().pushReaction(PistonBehavior.DESTROY)
+ .intState(STAGE)));
+ public static final Block CHERRY_SAPLING = register(new Block("cherry_sapling", builder().pushReaction(PistonBehavior.DESTROY)
+ .intState(STAGE)));
+ public static final Block DARK_OAK_SAPLING = register(new Block("dark_oak_sapling", builder().pushReaction(PistonBehavior.DESTROY)
+ .intState(STAGE)));
+ public static final Block MANGROVE_PROPAGULE = register(new Block("mangrove_propagule", builder().pushReaction(PistonBehavior.DESTROY)
+ .intState(AGE_4)
+ .booleanState(HANGING)
+ .intState(STAGE)
+ .booleanState(WATERLOGGED)));
+ public static final Block BEDROCK = register(new Block("bedrock", builder().destroyTime(-1.0f)));
+ public static final Block WATER = register(new WaterBlock("water", builder().destroyTime(100.0f).pushReaction(PistonBehavior.DESTROY)
+ .intState(LEVEL)));
+ public static final Block LAVA = register(new Block("lava", builder().destroyTime(100.0f).pushReaction(PistonBehavior.DESTROY)
+ .intState(LEVEL)));
+ public static final Block SAND = register(new Block("sand", builder().destroyTime(0.5f)));
+ public static final Block SUSPICIOUS_SAND = register(new Block("suspicious_sand", builder().setBlockEntity(BlockEntityType.BRUSHABLE_BLOCK).destroyTime(0.25f).pushReaction(PistonBehavior.DESTROY)
+ .intState(DUSTED)));
+ public static final Block RED_SAND = register(new Block("red_sand", builder().destroyTime(0.5f)));
+ public static final Block GRAVEL = register(new Block("gravel", builder().destroyTime(0.6f)));
+ public static final Block SUSPICIOUS_GRAVEL = register(new Block("suspicious_gravel", builder().setBlockEntity(BlockEntityType.BRUSHABLE_BLOCK).destroyTime(0.25f).pushReaction(PistonBehavior.DESTROY)
+ .intState(DUSTED)));
+ public static final Block GOLD_ORE = register(new Block("gold_ore", builder().requiresCorrectToolForDrops().destroyTime(3.0f)));
+ public static final Block DEEPSLATE_GOLD_ORE = register(new Block("deepslate_gold_ore", builder().requiresCorrectToolForDrops().destroyTime(4.5f)));
+ public static final Block IRON_ORE = register(new Block("iron_ore", builder().requiresCorrectToolForDrops().destroyTime(3.0f)));
+ public static final Block DEEPSLATE_IRON_ORE = register(new Block("deepslate_iron_ore", builder().requiresCorrectToolForDrops().destroyTime(4.5f)));
+ public static final Block COAL_ORE = register(new Block("coal_ore", builder().requiresCorrectToolForDrops().destroyTime(3.0f)));
+ public static final Block DEEPSLATE_COAL_ORE = register(new Block("deepslate_coal_ore", builder().requiresCorrectToolForDrops().destroyTime(4.5f)));
+ public static final Block NETHER_GOLD_ORE = register(new Block("nether_gold_ore", builder().requiresCorrectToolForDrops().destroyTime(3.0f)));
+ public static final Block OAK_LOG = register(new Block("oak_log", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block SPRUCE_LOG = register(new Block("spruce_log", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block BIRCH_LOG = register(new Block("birch_log", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block JUNGLE_LOG = register(new Block("jungle_log", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block ACACIA_LOG = register(new Block("acacia_log", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block CHERRY_LOG = register(new Block("cherry_log", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block DARK_OAK_LOG = register(new Block("dark_oak_log", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block MANGROVE_LOG = register(new Block("mangrove_log", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block MANGROVE_ROOTS = register(new Block("mangrove_roots", builder().destroyTime(0.7f)
+ .booleanState(WATERLOGGED)));
+ public static final Block MUDDY_MANGROVE_ROOTS = register(new Block("muddy_mangrove_roots", builder().destroyTime(0.7f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block BAMBOO_BLOCK = register(new Block("bamboo_block", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block STRIPPED_SPRUCE_LOG = register(new Block("stripped_spruce_log", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block STRIPPED_BIRCH_LOG = register(new Block("stripped_birch_log", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block STRIPPED_JUNGLE_LOG = register(new Block("stripped_jungle_log", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block STRIPPED_ACACIA_LOG = register(new Block("stripped_acacia_log", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block STRIPPED_CHERRY_LOG = register(new Block("stripped_cherry_log", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block STRIPPED_DARK_OAK_LOG = register(new Block("stripped_dark_oak_log", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block STRIPPED_OAK_LOG = register(new Block("stripped_oak_log", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block STRIPPED_MANGROVE_LOG = register(new Block("stripped_mangrove_log", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block STRIPPED_BAMBOO_BLOCK = register(new Block("stripped_bamboo_block", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block OAK_WOOD = register(new Block("oak_wood", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block SPRUCE_WOOD = register(new Block("spruce_wood", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block BIRCH_WOOD = register(new Block("birch_wood", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block JUNGLE_WOOD = register(new Block("jungle_wood", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block ACACIA_WOOD = register(new Block("acacia_wood", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block CHERRY_WOOD = register(new Block("cherry_wood", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block DARK_OAK_WOOD = register(new Block("dark_oak_wood", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block MANGROVE_WOOD = register(new Block("mangrove_wood", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block STRIPPED_OAK_WOOD = register(new Block("stripped_oak_wood", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block STRIPPED_SPRUCE_WOOD = register(new Block("stripped_spruce_wood", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block STRIPPED_BIRCH_WOOD = register(new Block("stripped_birch_wood", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block STRIPPED_JUNGLE_WOOD = register(new Block("stripped_jungle_wood", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block STRIPPED_ACACIA_WOOD = register(new Block("stripped_acacia_wood", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block STRIPPED_CHERRY_WOOD = register(new Block("stripped_cherry_wood", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block STRIPPED_DARK_OAK_WOOD = register(new Block("stripped_dark_oak_wood", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block STRIPPED_MANGROVE_WOOD = register(new Block("stripped_mangrove_wood", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block OAK_LEAVES = register(new Block("oak_leaves", builder().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY)
+ .intState(DISTANCE)
+ .booleanState(PERSISTENT)
+ .booleanState(WATERLOGGED)));
+ public static final Block SPRUCE_LEAVES = register(new Block("spruce_leaves", builder().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY)
+ .intState(DISTANCE)
+ .booleanState(PERSISTENT)
+ .booleanState(WATERLOGGED)));
+ public static final Block BIRCH_LEAVES = register(new Block("birch_leaves", builder().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY)
+ .intState(DISTANCE)
+ .booleanState(PERSISTENT)
+ .booleanState(WATERLOGGED)));
+ public static final Block JUNGLE_LEAVES = register(new Block("jungle_leaves", builder().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY)
+ .intState(DISTANCE)
+ .booleanState(PERSISTENT)
+ .booleanState(WATERLOGGED)));
+ public static final Block ACACIA_LEAVES = register(new Block("acacia_leaves", builder().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY)
+ .intState(DISTANCE)
+ .booleanState(PERSISTENT)
+ .booleanState(WATERLOGGED)));
+ public static final Block CHERRY_LEAVES = register(new Block("cherry_leaves", builder().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY)
+ .intState(DISTANCE)
+ .booleanState(PERSISTENT)
+ .booleanState(WATERLOGGED)));
+ public static final Block DARK_OAK_LEAVES = register(new Block("dark_oak_leaves", builder().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY)
+ .intState(DISTANCE)
+ .booleanState(PERSISTENT)
+ .booleanState(WATERLOGGED)));
+ public static final Block MANGROVE_LEAVES = register(new Block("mangrove_leaves", builder().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY)
+ .intState(DISTANCE)
+ .booleanState(PERSISTENT)
+ .booleanState(WATERLOGGED)));
+ public static final Block AZALEA_LEAVES = register(new Block("azalea_leaves", builder().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY)
+ .intState(DISTANCE)
+ .booleanState(PERSISTENT)
+ .booleanState(WATERLOGGED)));
+ public static final Block FLOWERING_AZALEA_LEAVES = register(new Block("flowering_azalea_leaves", builder().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY)
+ .intState(DISTANCE)
+ .booleanState(PERSISTENT)
+ .booleanState(WATERLOGGED)));
+ public static final Block SPONGE = register(new Block("sponge", builder().destroyTime(0.6f)));
+ public static final Block WET_SPONGE = register(new Block("wet_sponge", builder().destroyTime(0.6f)));
+ public static final Block GLASS = register(new Block("glass", builder().destroyTime(0.3f)));
+ public static final Block LAPIS_ORE = register(new Block("lapis_ore", builder().requiresCorrectToolForDrops().destroyTime(3.0f)));
+ public static final Block DEEPSLATE_LAPIS_ORE = register(new Block("deepslate_lapis_ore", builder().requiresCorrectToolForDrops().destroyTime(4.5f)));
+ public static final Block LAPIS_BLOCK = register(new Block("lapis_block", builder().requiresCorrectToolForDrops().destroyTime(3.0f)));
+ public static final Block DISPENSER = register(new Block("dispenser", builder().setBlockEntity(BlockEntityType.DISPENSER).requiresCorrectToolForDrops().destroyTime(3.5f)
+ .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN)
+ .booleanState(TRIGGERED)));
+ public static final Block SANDSTONE = register(new Block("sandstone", builder().requiresCorrectToolForDrops().destroyTime(0.8f)));
+ public static final Block CHISELED_SANDSTONE = register(new Block("chiseled_sandstone", builder().requiresCorrectToolForDrops().destroyTime(0.8f)));
+ public static final Block CUT_SANDSTONE = register(new Block("cut_sandstone", builder().requiresCorrectToolForDrops().destroyTime(0.8f)));
+ public static final Block NOTE_BLOCK = register(new Block("note_block", builder().destroyTime(0.8f)
+ .enumState(NOTEBLOCK_INSTRUMENT)
+ .intState(NOTE)
+ .booleanState(POWERED)));
+ public static final Block WHITE_BED = register(new BedBlock("white_bed", 0, builder().setBlockEntity(BlockEntityType.BED).destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(OCCUPIED)
+ .enumState(BED_PART)));
+ public static final Block ORANGE_BED = register(new BedBlock("orange_bed", 1, builder().setBlockEntity(BlockEntityType.BED).destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(OCCUPIED)
+ .enumState(BED_PART)));
+ public static final Block MAGENTA_BED = register(new BedBlock("magenta_bed", 2, builder().setBlockEntity(BlockEntityType.BED).destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(OCCUPIED)
+ .enumState(BED_PART)));
+ public static final Block LIGHT_BLUE_BED = register(new BedBlock("light_blue_bed", 3, builder().setBlockEntity(BlockEntityType.BED).destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(OCCUPIED)
+ .enumState(BED_PART)));
+ public static final Block YELLOW_BED = register(new BedBlock("yellow_bed", 4, builder().setBlockEntity(BlockEntityType.BED).destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(OCCUPIED)
+ .enumState(BED_PART)));
+ public static final Block LIME_BED = register(new BedBlock("lime_bed", 5, builder().setBlockEntity(BlockEntityType.BED).destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(OCCUPIED)
+ .enumState(BED_PART)));
+ public static final Block PINK_BED = register(new BedBlock("pink_bed", 6, builder().setBlockEntity(BlockEntityType.BED).destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(OCCUPIED)
+ .enumState(BED_PART)));
+ public static final Block GRAY_BED = register(new BedBlock("gray_bed", 7, builder().setBlockEntity(BlockEntityType.BED).destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(OCCUPIED)
+ .enumState(BED_PART)));
+ public static final Block LIGHT_GRAY_BED = register(new BedBlock("light_gray_bed", 8, builder().setBlockEntity(BlockEntityType.BED).destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(OCCUPIED)
+ .enumState(BED_PART)));
+ public static final Block CYAN_BED = register(new BedBlock("cyan_bed", 9, builder().setBlockEntity(BlockEntityType.BED).destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(OCCUPIED)
+ .enumState(BED_PART)));
+ public static final Block PURPLE_BED = register(new BedBlock("purple_bed", 10, builder().setBlockEntity(BlockEntityType.BED).destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(OCCUPIED)
+ .enumState(BED_PART)));
+ public static final Block BLUE_BED = register(new BedBlock("blue_bed", 11, builder().setBlockEntity(BlockEntityType.BED).destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(OCCUPIED)
+ .enumState(BED_PART)));
+ public static final Block BROWN_BED = register(new BedBlock("brown_bed", 12, builder().setBlockEntity(BlockEntityType.BED).destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(OCCUPIED)
+ .enumState(BED_PART)));
+ public static final Block GREEN_BED = register(new BedBlock("green_bed", 13, builder().setBlockEntity(BlockEntityType.BED).destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(OCCUPIED)
+ .enumState(BED_PART)));
+ public static final Block RED_BED = register(new BedBlock("red_bed", 14, builder().setBlockEntity(BlockEntityType.BED).destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(OCCUPIED)
+ .enumState(BED_PART)));
+ public static final Block BLACK_BED = register(new BedBlock("black_bed", 15, builder().setBlockEntity(BlockEntityType.BED).destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(OCCUPIED)
+ .enumState(BED_PART)));
+ public static final Block POWERED_RAIL = register(new Block("powered_rail", builder().destroyTime(0.7f)
+ .booleanState(POWERED)
+ .enumState(RAIL_SHAPE_STRAIGHT)
+ .booleanState(WATERLOGGED)));
+ public static final Block DETECTOR_RAIL = register(new Block("detector_rail", builder().destroyTime(0.7f)
+ .booleanState(POWERED)
+ .enumState(RAIL_SHAPE_STRAIGHT)
+ .booleanState(WATERLOGGED)));
+ public static final Block STICKY_PISTON = register(new PistonBlock("sticky_piston", builder().destroyTime(1.5f).pushReaction(PistonBehavior.BLOCK)
+ .booleanState(EXTENDED)
+ .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN)));
+ public static final Block COBWEB = register(new Block("cobweb", builder().requiresCorrectToolForDrops().destroyTime(4.0f).pushReaction(PistonBehavior.DESTROY)));
+ public static final Block SHORT_GRASS = register(new Block("short_grass", builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block FERN = register(new Block("fern", builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block DEAD_BUSH = register(new Block("dead_bush", builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block SEAGRASS = register(new Block("seagrass", builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block TALL_SEAGRASS = register(new Block("tall_seagrass", builder().pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.SEAGRASS)
+ .enumState(DOUBLE_BLOCK_HALF)));
+ public static final Block PISTON = register(new PistonBlock("piston", builder().destroyTime(1.5f).pushReaction(PistonBehavior.BLOCK)
+ .booleanState(EXTENDED)
+ .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN)));
+ public static final Block PISTON_HEAD = register(new PistonHeadBlock("piston_head", builder().destroyTime(1.5f).pushReaction(PistonBehavior.BLOCK)
+ .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN)
+ .booleanState(SHORT)
+ .enumState(PISTON_TYPE)));
+ public static final Block WHITE_WOOL = register(new Block("white_wool", builder().destroyTime(0.8f)));
+ public static final Block ORANGE_WOOL = register(new Block("orange_wool", builder().destroyTime(0.8f)));
+ public static final Block MAGENTA_WOOL = register(new Block("magenta_wool", builder().destroyTime(0.8f)));
+ public static final Block LIGHT_BLUE_WOOL = register(new Block("light_blue_wool", builder().destroyTime(0.8f)));
+ public static final Block YELLOW_WOOL = register(new Block("yellow_wool", builder().destroyTime(0.8f)));
+ public static final Block LIME_WOOL = register(new Block("lime_wool", builder().destroyTime(0.8f)));
+ public static final Block PINK_WOOL = register(new Block("pink_wool", builder().destroyTime(0.8f)));
+ public static final Block GRAY_WOOL = register(new Block("gray_wool", builder().destroyTime(0.8f)));
+ public static final Block LIGHT_GRAY_WOOL = register(new Block("light_gray_wool", builder().destroyTime(0.8f)));
+ public static final Block CYAN_WOOL = register(new Block("cyan_wool", builder().destroyTime(0.8f)));
+ public static final Block PURPLE_WOOL = register(new Block("purple_wool", builder().destroyTime(0.8f)));
+ public static final Block BLUE_WOOL = register(new Block("blue_wool", builder().destroyTime(0.8f)));
+ public static final Block BROWN_WOOL = register(new Block("brown_wool", builder().destroyTime(0.8f)));
+ public static final Block GREEN_WOOL = register(new Block("green_wool", builder().destroyTime(0.8f)));
+ public static final Block RED_WOOL = register(new Block("red_wool", builder().destroyTime(0.8f)));
+ public static final Block BLACK_WOOL = register(new Block("black_wool", builder().destroyTime(0.8f)));
+ public static final Block MOVING_PISTON = register(new MovingPistonBlock("moving_piston", builder().setBlockEntity(BlockEntityType.PISTON).destroyTime(-1.0f).pushReaction(PistonBehavior.BLOCK)
+ .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN)
+ .enumState(PISTON_TYPE)));
+ public static final Block DANDELION = register(new Block("dandelion", builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block TORCHFLOWER = register(new Block("torchflower", builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block POPPY = register(new Block("poppy", builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block BLUE_ORCHID = register(new Block("blue_orchid", builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block ALLIUM = register(new Block("allium", builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block AZURE_BLUET = register(new Block("azure_bluet", builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block RED_TULIP = register(new Block("red_tulip", builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block ORANGE_TULIP = register(new Block("orange_tulip", builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block WHITE_TULIP = register(new Block("white_tulip", builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block PINK_TULIP = register(new Block("pink_tulip", builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block OXEYE_DAISY = register(new Block("oxeye_daisy", builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block CORNFLOWER = register(new Block("cornflower", builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block WITHER_ROSE = register(new Block("wither_rose", builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block LILY_OF_THE_VALLEY = register(new Block("lily_of_the_valley", builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block BROWN_MUSHROOM = register(new Block("brown_mushroom", builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block RED_MUSHROOM = register(new Block("red_mushroom", builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block GOLD_BLOCK = register(new Block("gold_block", builder().requiresCorrectToolForDrops().destroyTime(3.0f)));
+ public static final Block IRON_BLOCK = register(new Block("iron_block", builder().requiresCorrectToolForDrops().destroyTime(5.0f)));
+ public static final Block BRICKS = register(new Block("bricks", builder().requiresCorrectToolForDrops().destroyTime(2.0f)));
+ public static final Block TNT = register(new Block("tnt", builder()
+ .booleanState(UNSTABLE)));
+ public static final Block BOOKSHELF = register(new Block("bookshelf", builder().destroyTime(1.5f)));
+ public static final Block CHISELED_BOOKSHELF = register(new Block("chiseled_bookshelf", builder().setBlockEntity(BlockEntityType.CHISELED_BOOKSHELF).destroyTime(1.5f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(CHISELED_BOOKSHELF_SLOT_0_OCCUPIED)
+ .booleanState(CHISELED_BOOKSHELF_SLOT_1_OCCUPIED)
+ .booleanState(CHISELED_BOOKSHELF_SLOT_2_OCCUPIED)
+ .booleanState(CHISELED_BOOKSHELF_SLOT_3_OCCUPIED)
+ .booleanState(CHISELED_BOOKSHELF_SLOT_4_OCCUPIED)
+ .booleanState(CHISELED_BOOKSHELF_SLOT_5_OCCUPIED)));
+ public static final Block MOSSY_COBBLESTONE = register(new Block("mossy_cobblestone", builder().requiresCorrectToolForDrops().destroyTime(2.0f)));
+ public static final Block OBSIDIAN = register(new Block("obsidian", builder().requiresCorrectToolForDrops().destroyTime(50.0f)));
+ public static final Block TORCH = register(new Block("torch", builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block WALL_TORCH = register(new Block("wall_torch", builder().pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block FIRE = register(new Block("fire", builder().pushReaction(PistonBehavior.DESTROY)
+ .intState(AGE_15)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(SOUTH)
+ .booleanState(UP)
+ .booleanState(WEST)));
+ public static final Block SOUL_FIRE = register(new Block("soul_fire", builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block SPAWNER = register(new SpawnerBlock("spawner", builder().setBlockEntity(BlockEntityType.MOB_SPAWNER).requiresCorrectToolForDrops().destroyTime(5.0f)));
+ public static final Block OAK_STAIRS = register(new Block("oak_stairs", builder().destroyTime(2.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block CHEST = register(new ChestBlock("chest", builder().setBlockEntity(BlockEntityType.CHEST).destroyTime(2.5f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(CHEST_TYPE, ChestType.VALUES)
+ .booleanState(WATERLOGGED)));
+ public static final Block REDSTONE_WIRE = register(new Block("redstone_wire", builder().pushReaction(PistonBehavior.DESTROY)
+ .enumState(EAST_REDSTONE)
+ .enumState(NORTH_REDSTONE)
+ .intState(POWER)
+ .enumState(SOUTH_REDSTONE)
+ .enumState(WEST_REDSTONE)));
+ public static final Block DIAMOND_ORE = register(new Block("diamond_ore", builder().requiresCorrectToolForDrops().destroyTime(3.0f)));
+ public static final Block DEEPSLATE_DIAMOND_ORE = register(new Block("deepslate_diamond_ore", builder().requiresCorrectToolForDrops().destroyTime(4.5f)));
+ public static final Block DIAMOND_BLOCK = register(new Block("diamond_block", builder().requiresCorrectToolForDrops().destroyTime(5.0f)));
+ public static final Block CRAFTING_TABLE = register(new Block("crafting_table", builder().destroyTime(2.5f)));
+ public static final Block WHEAT = register(new Block("wheat", builder().pushReaction(PistonBehavior.DESTROY)
+ .intState(AGE_7)));
+ public static final Block FARMLAND = register(new Block("farmland", builder().destroyTime(0.6f)
+ .intState(MOISTURE)));
+ public static final Block FURNACE = register(new FurnaceBlock("furnace", builder().setBlockEntity(BlockEntityType.FURNACE).requiresCorrectToolForDrops().destroyTime(3.5f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(LIT)));
+ public static final Block OAK_SIGN = register(new Block("oak_sign", builder().setBlockEntity(BlockEntityType.SIGN).destroyTime(1.0f)
+ .intState(ROTATION_16)
+ .booleanState(WATERLOGGED)));
+ public static final Block SPRUCE_SIGN = register(new Block("spruce_sign", builder().setBlockEntity(BlockEntityType.SIGN).destroyTime(1.0f)
+ .intState(ROTATION_16)
+ .booleanState(WATERLOGGED)));
+ public static final Block BIRCH_SIGN = register(new Block("birch_sign", builder().setBlockEntity(BlockEntityType.SIGN).destroyTime(1.0f)
+ .intState(ROTATION_16)
+ .booleanState(WATERLOGGED)));
+ public static final Block ACACIA_SIGN = register(new Block("acacia_sign", builder().setBlockEntity(BlockEntityType.SIGN).destroyTime(1.0f)
+ .intState(ROTATION_16)
+ .booleanState(WATERLOGGED)));
+ public static final Block CHERRY_SIGN = register(new Block("cherry_sign", builder().setBlockEntity(BlockEntityType.SIGN).destroyTime(1.0f)
+ .intState(ROTATION_16)
+ .booleanState(WATERLOGGED)));
+ public static final Block JUNGLE_SIGN = register(new Block("jungle_sign", builder().setBlockEntity(BlockEntityType.SIGN).destroyTime(1.0f)
+ .intState(ROTATION_16)
+ .booleanState(WATERLOGGED)));
+ public static final Block DARK_OAK_SIGN = register(new Block("dark_oak_sign", builder().setBlockEntity(BlockEntityType.SIGN).destroyTime(1.0f)
+ .intState(ROTATION_16)
+ .booleanState(WATERLOGGED)));
+ public static final Block MANGROVE_SIGN = register(new Block("mangrove_sign", builder().setBlockEntity(BlockEntityType.SIGN).destroyTime(1.0f)
+ .intState(ROTATION_16)
+ .booleanState(WATERLOGGED)));
+ public static final Block BAMBOO_SIGN = register(new Block("bamboo_sign", builder().setBlockEntity(BlockEntityType.SIGN).destroyTime(1.0f)
+ .intState(ROTATION_16)
+ .booleanState(WATERLOGGED)));
+ public static final Block OAK_DOOR = register(new DoorBlock("oak_door", builder().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(DOUBLE_BLOCK_HALF)
+ .enumState(DOOR_HINGE)
+ .booleanState(OPEN)
+ .booleanState(POWERED)));
+ public static final Block LADDER = register(new Block("ladder", builder().destroyTime(0.4f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(WATERLOGGED)));
+ public static final Block RAIL = register(new Block("rail", builder().destroyTime(0.7f)
+ .enumState(RAIL_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block COBBLESTONE_STAIRS = register(new Block("cobblestone_stairs", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block OAK_WALL_SIGN = register(new Block("oak_wall_sign", builder().setBlockEntity(BlockEntityType.SIGN).destroyTime(1.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(WATERLOGGED)));
+ public static final Block SPRUCE_WALL_SIGN = register(new Block("spruce_wall_sign", builder().setBlockEntity(BlockEntityType.SIGN).destroyTime(1.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(WATERLOGGED)));
+ public static final Block BIRCH_WALL_SIGN = register(new Block("birch_wall_sign", builder().setBlockEntity(BlockEntityType.SIGN).destroyTime(1.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(WATERLOGGED)));
+ public static final Block ACACIA_WALL_SIGN = register(new Block("acacia_wall_sign", builder().setBlockEntity(BlockEntityType.SIGN).destroyTime(1.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(WATERLOGGED)));
+ public static final Block CHERRY_WALL_SIGN = register(new Block("cherry_wall_sign", builder().setBlockEntity(BlockEntityType.SIGN).destroyTime(1.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(WATERLOGGED)));
+ public static final Block JUNGLE_WALL_SIGN = register(new Block("jungle_wall_sign", builder().setBlockEntity(BlockEntityType.SIGN).destroyTime(1.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(WATERLOGGED)));
+ public static final Block DARK_OAK_WALL_SIGN = register(new Block("dark_oak_wall_sign", builder().setBlockEntity(BlockEntityType.SIGN).destroyTime(1.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(WATERLOGGED)));
+ public static final Block MANGROVE_WALL_SIGN = register(new Block("mangrove_wall_sign", builder().setBlockEntity(BlockEntityType.SIGN).destroyTime(1.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(WATERLOGGED)));
+ public static final Block BAMBOO_WALL_SIGN = register(new Block("bamboo_wall_sign", builder().setBlockEntity(BlockEntityType.SIGN).destroyTime(1.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(WATERLOGGED)));
+ public static final Block OAK_HANGING_SIGN = register(new Block("oak_hanging_sign", builder().setBlockEntity(BlockEntityType.HANGING_SIGN).destroyTime(1.0f)
+ .booleanState(ATTACHED)
+ .intState(ROTATION_16)
+ .booleanState(WATERLOGGED)));
+ public static final Block SPRUCE_HANGING_SIGN = register(new Block("spruce_hanging_sign", builder().setBlockEntity(BlockEntityType.HANGING_SIGN).destroyTime(1.0f)
+ .booleanState(ATTACHED)
+ .intState(ROTATION_16)
+ .booleanState(WATERLOGGED)));
+ public static final Block BIRCH_HANGING_SIGN = register(new Block("birch_hanging_sign", builder().setBlockEntity(BlockEntityType.HANGING_SIGN).destroyTime(1.0f)
+ .booleanState(ATTACHED)
+ .intState(ROTATION_16)
+ .booleanState(WATERLOGGED)));
+ public static final Block ACACIA_HANGING_SIGN = register(new Block("acacia_hanging_sign", builder().setBlockEntity(BlockEntityType.HANGING_SIGN).destroyTime(1.0f)
+ .booleanState(ATTACHED)
+ .intState(ROTATION_16)
+ .booleanState(WATERLOGGED)));
+ public static final Block CHERRY_HANGING_SIGN = register(new Block("cherry_hanging_sign", builder().setBlockEntity(BlockEntityType.HANGING_SIGN).destroyTime(1.0f)
+ .booleanState(ATTACHED)
+ .intState(ROTATION_16)
+ .booleanState(WATERLOGGED)));
+ public static final Block JUNGLE_HANGING_SIGN = register(new Block("jungle_hanging_sign", builder().setBlockEntity(BlockEntityType.HANGING_SIGN).destroyTime(1.0f)
+ .booleanState(ATTACHED)
+ .intState(ROTATION_16)
+ .booleanState(WATERLOGGED)));
+ public static final Block DARK_OAK_HANGING_SIGN = register(new Block("dark_oak_hanging_sign", builder().setBlockEntity(BlockEntityType.HANGING_SIGN).destroyTime(1.0f)
+ .booleanState(ATTACHED)
+ .intState(ROTATION_16)
+ .booleanState(WATERLOGGED)));
+ public static final Block CRIMSON_HANGING_SIGN = register(new Block("crimson_hanging_sign", builder().setBlockEntity(BlockEntityType.HANGING_SIGN).destroyTime(1.0f)
+ .booleanState(ATTACHED)
+ .intState(ROTATION_16)
+ .booleanState(WATERLOGGED)));
+ public static final Block WARPED_HANGING_SIGN = register(new Block("warped_hanging_sign", builder().setBlockEntity(BlockEntityType.HANGING_SIGN).destroyTime(1.0f)
+ .booleanState(ATTACHED)
+ .intState(ROTATION_16)
+ .booleanState(WATERLOGGED)));
+ public static final Block MANGROVE_HANGING_SIGN = register(new Block("mangrove_hanging_sign", builder().setBlockEntity(BlockEntityType.HANGING_SIGN).destroyTime(1.0f)
+ .booleanState(ATTACHED)
+ .intState(ROTATION_16)
+ .booleanState(WATERLOGGED)));
+ public static final Block BAMBOO_HANGING_SIGN = register(new Block("bamboo_hanging_sign", builder().setBlockEntity(BlockEntityType.HANGING_SIGN).destroyTime(1.0f)
+ .booleanState(ATTACHED)
+ .intState(ROTATION_16)
+ .booleanState(WATERLOGGED)));
+ public static final Block OAK_WALL_HANGING_SIGN = register(new Block("oak_wall_hanging_sign", builder().setBlockEntity(BlockEntityType.HANGING_SIGN).destroyTime(1.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(WATERLOGGED)));
+ public static final Block SPRUCE_WALL_HANGING_SIGN = register(new Block("spruce_wall_hanging_sign", builder().setBlockEntity(BlockEntityType.HANGING_SIGN).destroyTime(1.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(WATERLOGGED)));
+ public static final Block BIRCH_WALL_HANGING_SIGN = register(new Block("birch_wall_hanging_sign", builder().setBlockEntity(BlockEntityType.HANGING_SIGN).destroyTime(1.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(WATERLOGGED)));
+ public static final Block ACACIA_WALL_HANGING_SIGN = register(new Block("acacia_wall_hanging_sign", builder().setBlockEntity(BlockEntityType.HANGING_SIGN).destroyTime(1.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(WATERLOGGED)));
+ public static final Block CHERRY_WALL_HANGING_SIGN = register(new Block("cherry_wall_hanging_sign", builder().setBlockEntity(BlockEntityType.HANGING_SIGN).destroyTime(1.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(WATERLOGGED)));
+ public static final Block JUNGLE_WALL_HANGING_SIGN = register(new Block("jungle_wall_hanging_sign", builder().setBlockEntity(BlockEntityType.HANGING_SIGN).destroyTime(1.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(WATERLOGGED)));
+ public static final Block DARK_OAK_WALL_HANGING_SIGN = register(new Block("dark_oak_wall_hanging_sign", builder().setBlockEntity(BlockEntityType.HANGING_SIGN).destroyTime(1.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(WATERLOGGED)));
+ public static final Block MANGROVE_WALL_HANGING_SIGN = register(new Block("mangrove_wall_hanging_sign", builder().setBlockEntity(BlockEntityType.HANGING_SIGN).destroyTime(1.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(WATERLOGGED)));
+ public static final Block CRIMSON_WALL_HANGING_SIGN = register(new Block("crimson_wall_hanging_sign", builder().setBlockEntity(BlockEntityType.HANGING_SIGN).destroyTime(1.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(WATERLOGGED)));
+ public static final Block WARPED_WALL_HANGING_SIGN = register(new Block("warped_wall_hanging_sign", builder().setBlockEntity(BlockEntityType.HANGING_SIGN).destroyTime(1.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(WATERLOGGED)));
+ public static final Block BAMBOO_WALL_HANGING_SIGN = register(new Block("bamboo_wall_hanging_sign", builder().setBlockEntity(BlockEntityType.HANGING_SIGN).destroyTime(1.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(WATERLOGGED)));
+ public static final Block LEVER = register(new Block("lever", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(ATTACH_FACE)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(POWERED)));
+ public static final Block STONE_PRESSURE_PLATE = register(new Block("stone_pressure_plate", builder().requiresCorrectToolForDrops().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY)
+ .booleanState(POWERED)));
+ public static final Block IRON_DOOR = register(new DoorBlock("iron_door", builder().requiresCorrectToolForDrops().destroyTime(5.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(DOUBLE_BLOCK_HALF)
+ .enumState(DOOR_HINGE)
+ .booleanState(OPEN)
+ .booleanState(POWERED)));
+ public static final Block OAK_PRESSURE_PLATE = register(new Block("oak_pressure_plate", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY)
+ .booleanState(POWERED)));
+ public static final Block SPRUCE_PRESSURE_PLATE = register(new Block("spruce_pressure_plate", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY)
+ .booleanState(POWERED)));
+ public static final Block BIRCH_PRESSURE_PLATE = register(new Block("birch_pressure_plate", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY)
+ .booleanState(POWERED)));
+ public static final Block JUNGLE_PRESSURE_PLATE = register(new Block("jungle_pressure_plate", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY)
+ .booleanState(POWERED)));
+ public static final Block ACACIA_PRESSURE_PLATE = register(new Block("acacia_pressure_plate", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY)
+ .booleanState(POWERED)));
+ public static final Block CHERRY_PRESSURE_PLATE = register(new Block("cherry_pressure_plate", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY)
+ .booleanState(POWERED)));
+ public static final Block DARK_OAK_PRESSURE_PLATE = register(new Block("dark_oak_pressure_plate", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY)
+ .booleanState(POWERED)));
+ public static final Block MANGROVE_PRESSURE_PLATE = register(new Block("mangrove_pressure_plate", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY)
+ .booleanState(POWERED)));
+ public static final Block BAMBOO_PRESSURE_PLATE = register(new Block("bamboo_pressure_plate", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY)
+ .booleanState(POWERED)));
+ public static final Block REDSTONE_ORE = register(new Block("redstone_ore", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .booleanState(LIT)));
+ public static final Block DEEPSLATE_REDSTONE_ORE = register(new Block("deepslate_redstone_ore", builder().requiresCorrectToolForDrops().destroyTime(4.5f)
+ .booleanState(LIT)));
+ public static final Block REDSTONE_TORCH = register(new Block("redstone_torch", builder().pushReaction(PistonBehavior.DESTROY)
+ .booleanState(LIT)));
+ public static final Block REDSTONE_WALL_TORCH = register(new Block("redstone_wall_torch", builder().pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(LIT)));
+ public static final Block STONE_BUTTON = register(new Block("stone_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(ATTACH_FACE)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(POWERED)));
+ public static final Block SNOW = register(new Block("snow", builder().requiresCorrectToolForDrops().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY)
+ .intState(LAYERS)));
+ public static final Block ICE = register(new Block("ice", builder().destroyTime(0.5f)));
+ public static final Block SNOW_BLOCK = register(new Block("snow_block", builder().requiresCorrectToolForDrops().destroyTime(0.2f)));
+ public static final Block CACTUS = register(new Block("cactus", builder().destroyTime(0.4f).pushReaction(PistonBehavior.DESTROY)
+ .intState(AGE_15)));
+ public static final Block CLAY = register(new Block("clay", builder().destroyTime(0.6f)));
+ public static final Block SUGAR_CANE = register(new Block("sugar_cane", builder().pushReaction(PistonBehavior.DESTROY)
+ .intState(AGE_15)));
+ public static final Block JUKEBOX = register(new Block("jukebox", builder().setBlockEntity(BlockEntityType.JUKEBOX).destroyTime(2.0f)
+ .booleanState(HAS_RECORD)));
+ public static final Block OAK_FENCE = register(new Block("oak_fence", builder().destroyTime(2.0f)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(SOUTH)
+ .booleanState(WATERLOGGED)
+ .booleanState(WEST)));
+ public static final Block NETHERRACK = register(new Block("netherrack", builder().requiresCorrectToolForDrops().destroyTime(0.4f)));
+ public static final Block SOUL_SAND = register(new Block("soul_sand", builder().destroyTime(0.5f)));
+ public static final Block SOUL_SOIL = register(new Block("soul_soil", builder().destroyTime(0.5f)));
+ public static final Block BASALT = register(new Block("basalt", builder().requiresCorrectToolForDrops().destroyTime(1.25f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block POLISHED_BASALT = register(new Block("polished_basalt", builder().requiresCorrectToolForDrops().destroyTime(1.25f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block SOUL_TORCH = register(new Block("soul_torch", builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block SOUL_WALL_TORCH = register(new Block("soul_wall_torch", builder().pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block GLOWSTONE = register(new Block("glowstone", builder().destroyTime(0.3f)));
+ public static final Block NETHER_PORTAL = register(new Block("nether_portal", builder().destroyTime(-1.0f).pushReaction(PistonBehavior.BLOCK)
+ .enumState(HORIZONTAL_AXIS, Axis.X, Axis.Z)));
+ public static final Block CARVED_PUMPKIN = register(new Block("carved_pumpkin", builder().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block JACK_O_LANTERN = register(new Block("jack_o_lantern", builder().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block CAKE = register(new Block("cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY)
+ .intState(BITES)));
+ public static final Block REPEATER = register(new Block("repeater", builder().pushReaction(PistonBehavior.DESTROY)
+ .intState(DELAY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(LOCKED)
+ .booleanState(POWERED)));
+ public static final Block WHITE_STAINED_GLASS = register(new Block("white_stained_glass", builder().destroyTime(0.3f)));
+ public static final Block ORANGE_STAINED_GLASS = register(new Block("orange_stained_glass", builder().destroyTime(0.3f)));
+ public static final Block MAGENTA_STAINED_GLASS = register(new Block("magenta_stained_glass", builder().destroyTime(0.3f)));
+ public static final Block LIGHT_BLUE_STAINED_GLASS = register(new Block("light_blue_stained_glass", builder().destroyTime(0.3f)));
+ public static final Block YELLOW_STAINED_GLASS = register(new Block("yellow_stained_glass", builder().destroyTime(0.3f)));
+ public static final Block LIME_STAINED_GLASS = register(new Block("lime_stained_glass", builder().destroyTime(0.3f)));
+ public static final Block PINK_STAINED_GLASS = register(new Block("pink_stained_glass", builder().destroyTime(0.3f)));
+ public static final Block GRAY_STAINED_GLASS = register(new Block("gray_stained_glass", builder().destroyTime(0.3f)));
+ public static final Block LIGHT_GRAY_STAINED_GLASS = register(new Block("light_gray_stained_glass", builder().destroyTime(0.3f)));
+ public static final Block CYAN_STAINED_GLASS = register(new Block("cyan_stained_glass", builder().destroyTime(0.3f)));
+ public static final Block PURPLE_STAINED_GLASS = register(new Block("purple_stained_glass", builder().destroyTime(0.3f)));
+ public static final Block BLUE_STAINED_GLASS = register(new Block("blue_stained_glass", builder().destroyTime(0.3f)));
+ public static final Block BROWN_STAINED_GLASS = register(new Block("brown_stained_glass", builder().destroyTime(0.3f)));
+ public static final Block GREEN_STAINED_GLASS = register(new Block("green_stained_glass", builder().destroyTime(0.3f)));
+ public static final Block RED_STAINED_GLASS = register(new Block("red_stained_glass", builder().destroyTime(0.3f)));
+ public static final Block BLACK_STAINED_GLASS = register(new Block("black_stained_glass", builder().destroyTime(0.3f)));
+ public static final Block OAK_TRAPDOOR = register(new TrapDoorBlock("oak_trapdoor", builder().destroyTime(3.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .booleanState(OPEN)
+ .booleanState(POWERED)
+ .booleanState(WATERLOGGED)));
+ public static final Block SPRUCE_TRAPDOOR = register(new TrapDoorBlock("spruce_trapdoor", builder().destroyTime(3.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .booleanState(OPEN)
+ .booleanState(POWERED)
+ .booleanState(WATERLOGGED)));
+ public static final Block BIRCH_TRAPDOOR = register(new TrapDoorBlock("birch_trapdoor", builder().destroyTime(3.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .booleanState(OPEN)
+ .booleanState(POWERED)
+ .booleanState(WATERLOGGED)));
+ public static final Block JUNGLE_TRAPDOOR = register(new TrapDoorBlock("jungle_trapdoor", builder().destroyTime(3.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .booleanState(OPEN)
+ .booleanState(POWERED)
+ .booleanState(WATERLOGGED)));
+ public static final Block ACACIA_TRAPDOOR = register(new TrapDoorBlock("acacia_trapdoor", builder().destroyTime(3.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .booleanState(OPEN)
+ .booleanState(POWERED)
+ .booleanState(WATERLOGGED)));
+ public static final Block CHERRY_TRAPDOOR = register(new TrapDoorBlock("cherry_trapdoor", builder().destroyTime(3.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .booleanState(OPEN)
+ .booleanState(POWERED)
+ .booleanState(WATERLOGGED)));
+ public static final Block DARK_OAK_TRAPDOOR = register(new TrapDoorBlock("dark_oak_trapdoor", builder().destroyTime(3.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .booleanState(OPEN)
+ .booleanState(POWERED)
+ .booleanState(WATERLOGGED)));
+ public static final Block MANGROVE_TRAPDOOR = register(new TrapDoorBlock("mangrove_trapdoor", builder().destroyTime(3.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .booleanState(OPEN)
+ .booleanState(POWERED)
+ .booleanState(WATERLOGGED)));
+ public static final Block BAMBOO_TRAPDOOR = register(new TrapDoorBlock("bamboo_trapdoor", builder().destroyTime(3.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .booleanState(OPEN)
+ .booleanState(POWERED)
+ .booleanState(WATERLOGGED)));
+ public static final Block STONE_BRICKS = register(new Block("stone_bricks", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
+ public static final Block MOSSY_STONE_BRICKS = register(new Block("mossy_stone_bricks", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
+ public static final Block CRACKED_STONE_BRICKS = register(new Block("cracked_stone_bricks", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
+ public static final Block CHISELED_STONE_BRICKS = register(new Block("chiseled_stone_bricks", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
+ public static final Block PACKED_MUD = register(new Block("packed_mud", builder().destroyTime(1.0f)));
+ public static final Block MUD_BRICKS = register(new Block("mud_bricks", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
+ public static final Block INFESTED_STONE = register(new Block("infested_stone", builder().destroyTime(0.75f)));
+ public static final Block INFESTED_COBBLESTONE = register(new Block("infested_cobblestone", builder().destroyTime(1.0f)));
+ public static final Block INFESTED_STONE_BRICKS = register(new Block("infested_stone_bricks", builder().destroyTime(0.75f)));
+ public static final Block INFESTED_MOSSY_STONE_BRICKS = register(new Block("infested_mossy_stone_bricks", builder().destroyTime(0.75f)));
+ public static final Block INFESTED_CRACKED_STONE_BRICKS = register(new Block("infested_cracked_stone_bricks", builder().destroyTime(0.75f)));
+ public static final Block INFESTED_CHISELED_STONE_BRICKS = register(new Block("infested_chiseled_stone_bricks", builder().destroyTime(0.75f)));
+ public static final Block BROWN_MUSHROOM_BLOCK = register(new Block("brown_mushroom_block", builder().destroyTime(0.2f)
+ .booleanState(DOWN)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(SOUTH)
+ .booleanState(UP)
+ .booleanState(WEST)));
+ public static final Block RED_MUSHROOM_BLOCK = register(new Block("red_mushroom_block", builder().destroyTime(0.2f)
+ .booleanState(DOWN)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(SOUTH)
+ .booleanState(UP)
+ .booleanState(WEST)));
+ public static final Block MUSHROOM_STEM = register(new Block("mushroom_stem", builder().destroyTime(0.2f)
+ .booleanState(DOWN)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(SOUTH)
+ .booleanState(UP)
+ .booleanState(WEST)));
+ public static final Block IRON_BARS = register(new Block("iron_bars", builder().requiresCorrectToolForDrops().destroyTime(5.0f)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(SOUTH)
+ .booleanState(WATERLOGGED)
+ .booleanState(WEST)));
+ public static final Block CHAIN = register(new Block("chain", builder().requiresCorrectToolForDrops().destroyTime(5.0f)
+ .enumState(AXIS, Axis.VALUES)
+ .booleanState(WATERLOGGED)));
+ public static final Block GLASS_PANE = register(new Block("glass_pane", builder().destroyTime(0.3f)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(SOUTH)
+ .booleanState(WATERLOGGED)
+ .booleanState(WEST)));
+ public static final Block PUMPKIN = register(new Block("pumpkin", builder().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY)));
+ public static final Block MELON = register(new Block("melon", builder().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY)));
+ public static final Block ATTACHED_PUMPKIN_STEM = register(new Block("attached_pumpkin_stem", builder().pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.PUMPKIN_SEEDS)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block ATTACHED_MELON_STEM = register(new Block("attached_melon_stem", builder().pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.MELON_SEEDS)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block PUMPKIN_STEM = register(new Block("pumpkin_stem", builder().pushReaction(PistonBehavior.DESTROY)
+ .intState(AGE_7)));
+ public static final Block MELON_STEM = register(new Block("melon_stem", builder().pushReaction(PistonBehavior.DESTROY)
+ .intState(AGE_7)));
+ public static final Block VINE = register(new Block("vine", builder().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(SOUTH)
+ .booleanState(UP)
+ .booleanState(WEST)));
+ public static final Block GLOW_LICHEN = register(new Block("glow_lichen", builder().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY)
+ .booleanState(DOWN)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(SOUTH)
+ .booleanState(UP)
+ .booleanState(WATERLOGGED)
+ .booleanState(WEST)));
+ public static final Block OAK_FENCE_GATE = register(new Block("oak_fence_gate", builder().destroyTime(2.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(IN_WALL)
+ .booleanState(OPEN)
+ .booleanState(POWERED)));
+ public static final Block BRICK_STAIRS = register(new Block("brick_stairs", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block STONE_BRICK_STAIRS = register(new Block("stone_brick_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block MUD_BRICK_STAIRS = register(new Block("mud_brick_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block MYCELIUM = register(new Block("mycelium", builder().destroyTime(0.6f)
+ .booleanState(SNOWY)));
+ public static final Block LILY_PAD = register(new Block("lily_pad", builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block NETHER_BRICKS = register(new Block("nether_bricks", builder().requiresCorrectToolForDrops().destroyTime(2.0f)));
+ public static final Block NETHER_BRICK_FENCE = register(new Block("nether_brick_fence", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(SOUTH)
+ .booleanState(WATERLOGGED)
+ .booleanState(WEST)));
+ public static final Block NETHER_BRICK_STAIRS = register(new Block("nether_brick_stairs", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block NETHER_WART = register(new Block("nether_wart", builder().pushReaction(PistonBehavior.DESTROY)
+ .intState(AGE_3)));
+ public static final Block ENCHANTING_TABLE = register(new Block("enchanting_table", builder().setBlockEntity(BlockEntityType.ENCHANTING_TABLE).requiresCorrectToolForDrops().destroyTime(5.0f)));
+ public static final Block BREWING_STAND = register(new Block("brewing_stand", builder().setBlockEntity(BlockEntityType.BREWING_STAND).requiresCorrectToolForDrops().destroyTime(0.5f)
+ .booleanState(HAS_BOTTLE_0)
+ .booleanState(HAS_BOTTLE_1)
+ .booleanState(HAS_BOTTLE_2)));
+ public static final Block CAULDRON = register(new CauldronBlock("cauldron", builder().requiresCorrectToolForDrops().destroyTime(2.0f)));
+ public static final Block WATER_CAULDRON = register(new CauldronBlock("water_cauldron", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .intState(LEVEL_CAULDRON)));
+ public static final Block LAVA_CAULDRON = register(new CauldronBlock("lava_cauldron", builder().requiresCorrectToolForDrops().destroyTime(2.0f)));
+ public static final Block POWDER_SNOW_CAULDRON = register(new CauldronBlock("powder_snow_cauldron", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .intState(LEVEL_CAULDRON)));
+ public static final Block END_PORTAL = register(new Block("end_portal", builder().setBlockEntity(BlockEntityType.END_PORTAL).destroyTime(-1.0f).pushReaction(PistonBehavior.BLOCK)));
+ public static final Block END_PORTAL_FRAME = register(new Block("end_portal_frame", builder().destroyTime(-1.0f)
+ .booleanState(EYE)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block END_STONE = register(new Block("end_stone", builder().requiresCorrectToolForDrops().destroyTime(3.0f)));
+ public static final Block DRAGON_EGG = register(new Block("dragon_egg", builder().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY)));
+ public static final Block REDSTONE_LAMP = register(new Block("redstone_lamp", builder().destroyTime(0.3f)
+ .booleanState(LIT)));
+ public static final Block COCOA = register(new Block("cocoa", builder().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY)
+ .intState(AGE_2)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block SANDSTONE_STAIRS = register(new Block("sandstone_stairs", builder().requiresCorrectToolForDrops().destroyTime(0.8f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block EMERALD_ORE = register(new Block("emerald_ore", builder().requiresCorrectToolForDrops().destroyTime(3.0f)));
+ public static final Block DEEPSLATE_EMERALD_ORE = register(new Block("deepslate_emerald_ore", builder().requiresCorrectToolForDrops().destroyTime(4.5f)));
+ public static final Block ENDER_CHEST = register(new Block("ender_chest", builder().setBlockEntity(BlockEntityType.ENDER_CHEST).requiresCorrectToolForDrops().destroyTime(22.5f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(WATERLOGGED)));
+ public static final Block TRIPWIRE_HOOK = register(new Block("tripwire_hook", builder().pushReaction(PistonBehavior.DESTROY)
+ .booleanState(ATTACHED)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(POWERED)));
+ public static final Block TRIPWIRE = register(new Block("tripwire", builder().pushReaction(PistonBehavior.DESTROY)
+ .booleanState(ATTACHED)
+ .booleanState(DISARMED)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(POWERED)
+ .booleanState(SOUTH)
+ .booleanState(WEST)));
+ public static final Block EMERALD_BLOCK = register(new Block("emerald_block", builder().requiresCorrectToolForDrops().destroyTime(5.0f)));
+ public static final Block SPRUCE_STAIRS = register(new Block("spruce_stairs", builder().destroyTime(2.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block BIRCH_STAIRS = register(new Block("birch_stairs", builder().destroyTime(2.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block JUNGLE_STAIRS = register(new Block("jungle_stairs", builder().destroyTime(2.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block COMMAND_BLOCK = register(new Block("command_block", builder().setBlockEntity(BlockEntityType.COMMAND_BLOCK).requiresCorrectToolForDrops().destroyTime(-1.0f)
+ .booleanState(CONDITIONAL)
+ .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN)));
+ public static final Block BEACON = register(new Block("beacon", builder().setBlockEntity(BlockEntityType.BEACON).destroyTime(3.0f)));
+ public static final Block COBBLESTONE_WALL = register(new Block("cobblestone_wall", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .enumState(EAST_WALL)
+ .enumState(NORTH_WALL)
+ .enumState(SOUTH_WALL)
+ .booleanState(UP)
+ .booleanState(WATERLOGGED)
+ .enumState(WEST_WALL)));
+ public static final Block MOSSY_COBBLESTONE_WALL = register(new Block("mossy_cobblestone_wall", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .enumState(EAST_WALL)
+ .enumState(NORTH_WALL)
+ .enumState(SOUTH_WALL)
+ .booleanState(UP)
+ .booleanState(WATERLOGGED)
+ .enumState(WEST_WALL)));
+ public static final Block FLOWER_POT = register(new FlowerPotBlock("flower_pot", AIR, builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block POTTED_TORCHFLOWER = register(new FlowerPotBlock("potted_torchflower", TORCHFLOWER, builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block POTTED_OAK_SAPLING = register(new FlowerPotBlock("potted_oak_sapling", OAK_SAPLING, builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block POTTED_SPRUCE_SAPLING = register(new FlowerPotBlock("potted_spruce_sapling", SPRUCE_SAPLING, builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block POTTED_BIRCH_SAPLING = register(new FlowerPotBlock("potted_birch_sapling", BIRCH_SAPLING, builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block POTTED_JUNGLE_SAPLING = register(new FlowerPotBlock("potted_jungle_sapling", JUNGLE_SAPLING, builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block POTTED_ACACIA_SAPLING = register(new FlowerPotBlock("potted_acacia_sapling", ACACIA_SAPLING, builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block POTTED_CHERRY_SAPLING = register(new FlowerPotBlock("potted_cherry_sapling", CHERRY_SAPLING, builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block POTTED_DARK_OAK_SAPLING = register(new FlowerPotBlock("potted_dark_oak_sapling", DARK_OAK_SAPLING, builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block POTTED_MANGROVE_PROPAGULE = register(new FlowerPotBlock("potted_mangrove_propagule", MANGROVE_PROPAGULE, builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block POTTED_FERN = register(new FlowerPotBlock("potted_fern", FERN, builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block POTTED_DANDELION = register(new FlowerPotBlock("potted_dandelion", DANDELION, builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block POTTED_POPPY = register(new FlowerPotBlock("potted_poppy", POPPY, builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block POTTED_BLUE_ORCHID = register(new FlowerPotBlock("potted_blue_orchid", BLUE_ORCHID, builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block POTTED_ALLIUM = register(new FlowerPotBlock("potted_allium", ALLIUM, builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block POTTED_AZURE_BLUET = register(new FlowerPotBlock("potted_azure_bluet", AZURE_BLUET, builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block POTTED_RED_TULIP = register(new FlowerPotBlock("potted_red_tulip", RED_TULIP, builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block POTTED_ORANGE_TULIP = register(new FlowerPotBlock("potted_orange_tulip", ORANGE_TULIP, builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block POTTED_WHITE_TULIP = register(new FlowerPotBlock("potted_white_tulip", WHITE_TULIP, builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block POTTED_PINK_TULIP = register(new FlowerPotBlock("potted_pink_tulip", PINK_TULIP, builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block POTTED_OXEYE_DAISY = register(new FlowerPotBlock("potted_oxeye_daisy", OXEYE_DAISY, builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block POTTED_CORNFLOWER = register(new FlowerPotBlock("potted_cornflower", CORNFLOWER, builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block POTTED_LILY_OF_THE_VALLEY = register(new FlowerPotBlock("potted_lily_of_the_valley", LILY_OF_THE_VALLEY, builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block POTTED_WITHER_ROSE = register(new FlowerPotBlock("potted_wither_rose", WITHER_ROSE, builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block POTTED_RED_MUSHROOM = register(new FlowerPotBlock("potted_red_mushroom", RED_MUSHROOM, builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block POTTED_BROWN_MUSHROOM = register(new FlowerPotBlock("potted_brown_mushroom", BROWN_MUSHROOM, builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block POTTED_DEAD_BUSH = register(new FlowerPotBlock("potted_dead_bush", DEAD_BUSH, builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block POTTED_CACTUS = register(new FlowerPotBlock("potted_cactus", CACTUS, builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block CARROTS = register(new Block("carrots", builder().pushReaction(PistonBehavior.DESTROY)
+ .intState(AGE_7)));
+ public static final Block POTATOES = register(new Block("potatoes", builder().pushReaction(PistonBehavior.DESTROY)
+ .intState(AGE_7)));
+ public static final Block OAK_BUTTON = register(new Block("oak_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(ATTACH_FACE)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(POWERED)));
+ public static final Block SPRUCE_BUTTON = register(new Block("spruce_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(ATTACH_FACE)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(POWERED)));
+ public static final Block BIRCH_BUTTON = register(new Block("birch_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(ATTACH_FACE)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(POWERED)));
+ public static final Block JUNGLE_BUTTON = register(new Block("jungle_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(ATTACH_FACE)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(POWERED)));
+ public static final Block ACACIA_BUTTON = register(new Block("acacia_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(ATTACH_FACE)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(POWERED)));
+ public static final Block CHERRY_BUTTON = register(new Block("cherry_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(ATTACH_FACE)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(POWERED)));
+ public static final Block DARK_OAK_BUTTON = register(new Block("dark_oak_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(ATTACH_FACE)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(POWERED)));
+ public static final Block MANGROVE_BUTTON = register(new Block("mangrove_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(ATTACH_FACE)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(POWERED)));
+ public static final Block BAMBOO_BUTTON = register(new Block("bamboo_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(ATTACH_FACE)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(POWERED)));
+ public static final Block SKELETON_SKULL = register(new SkullBlock("skeleton_skull", SkullBlock.Type.SKELETON, builder().setBlockEntity(BlockEntityType.SKULL).destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY)
+ .booleanState(POWERED)
+ .intState(ROTATION_16)));
+ public static final Block SKELETON_WALL_SKULL = register(new WallSkullBlock("skeleton_wall_skull", SkullBlock.Type.SKELETON, builder().setBlockEntity(BlockEntityType.SKULL).destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(POWERED)));
+ public static final Block WITHER_SKELETON_SKULL = register(new SkullBlock("wither_skeleton_skull", SkullBlock.Type.WITHER_SKELETON, builder().setBlockEntity(BlockEntityType.SKULL).destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY)
+ .booleanState(POWERED)
+ .intState(ROTATION_16)));
+ public static final Block WITHER_SKELETON_WALL_SKULL = register(new WallSkullBlock("wither_skeleton_wall_skull", SkullBlock.Type.WITHER_SKELETON, builder().setBlockEntity(BlockEntityType.SKULL).destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(POWERED)));
+ public static final Block ZOMBIE_HEAD = register(new SkullBlock("zombie_head", SkullBlock.Type.ZOMBIE, builder().setBlockEntity(BlockEntityType.SKULL).destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY)
+ .booleanState(POWERED)
+ .intState(ROTATION_16)));
+ public static final Block ZOMBIE_WALL_HEAD = register(new WallSkullBlock("zombie_wall_head", SkullBlock.Type.ZOMBIE, builder().setBlockEntity(BlockEntityType.SKULL).destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(POWERED)));
+ public static final Block PLAYER_HEAD = register(new SkullBlock("player_head", SkullBlock.Type.PLAYER, builder().setBlockEntity(BlockEntityType.SKULL).destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY)
+ .booleanState(POWERED)
+ .intState(ROTATION_16)));
+ public static final Block PLAYER_WALL_HEAD = register(new WallSkullBlock("player_wall_head", SkullBlock.Type.PLAYER, builder().setBlockEntity(BlockEntityType.SKULL).destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(POWERED)));
+ public static final Block CREEPER_HEAD = register(new SkullBlock("creeper_head", SkullBlock.Type.CREEPER, builder().setBlockEntity(BlockEntityType.SKULL).destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY)
+ .booleanState(POWERED)
+ .intState(ROTATION_16)));
+ public static final Block CREEPER_WALL_HEAD = register(new WallSkullBlock("creeper_wall_head", SkullBlock.Type.CREEPER, builder().setBlockEntity(BlockEntityType.SKULL).destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(POWERED)));
+ public static final Block DRAGON_HEAD = register(new SkullBlock("dragon_head", SkullBlock.Type.DRAGON, builder().setBlockEntity(BlockEntityType.SKULL).destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY)
+ .booleanState(POWERED)
+ .intState(ROTATION_16)));
+ public static final Block DRAGON_WALL_HEAD = register(new WallSkullBlock("dragon_wall_head", SkullBlock.Type.DRAGON, builder().setBlockEntity(BlockEntityType.SKULL).destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(POWERED)));
+ public static final Block PIGLIN_HEAD = register(new SkullBlock("piglin_head", SkullBlock.Type.PIGLIN, builder().setBlockEntity(BlockEntityType.SKULL).destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY)
+ .booleanState(POWERED)
+ .intState(ROTATION_16)));
+ public static final Block PIGLIN_WALL_HEAD = register(new WallSkullBlock("piglin_wall_head", SkullBlock.Type.PIGLIN, builder().setBlockEntity(BlockEntityType.SKULL).destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(POWERED)));
+ public static final Block ANVIL = register(new Block("anvil", builder().requiresCorrectToolForDrops().destroyTime(5.0f).pushReaction(PistonBehavior.BLOCK)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block CHIPPED_ANVIL = register(new Block("chipped_anvil", builder().requiresCorrectToolForDrops().destroyTime(5.0f).pushReaction(PistonBehavior.BLOCK)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block DAMAGED_ANVIL = register(new Block("damaged_anvil", builder().requiresCorrectToolForDrops().destroyTime(5.0f).pushReaction(PistonBehavior.BLOCK)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block TRAPPED_CHEST = register(new ChestBlock("trapped_chest", builder().setBlockEntity(BlockEntityType.TRAPPED_CHEST).destroyTime(2.5f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(CHEST_TYPE, ChestType.VALUES)
+ .booleanState(WATERLOGGED)));
+ public static final Block LIGHT_WEIGHTED_PRESSURE_PLATE = register(new Block("light_weighted_pressure_plate", builder().requiresCorrectToolForDrops().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY)
+ .intState(POWER)));
+ public static final Block HEAVY_WEIGHTED_PRESSURE_PLATE = register(new Block("heavy_weighted_pressure_plate", builder().requiresCorrectToolForDrops().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY)
+ .intState(POWER)));
+ public static final Block COMPARATOR = register(new Block("comparator", builder().setBlockEntity(BlockEntityType.COMPARATOR).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(MODE_COMPARATOR)
+ .booleanState(POWERED)));
+ public static final Block DAYLIGHT_DETECTOR = register(new Block("daylight_detector", builder().setBlockEntity(BlockEntityType.DAYLIGHT_DETECTOR).destroyTime(0.2f)
+ .booleanState(INVERTED)
+ .intState(POWER)));
+ public static final Block REDSTONE_BLOCK = register(new Block("redstone_block", builder().requiresCorrectToolForDrops().destroyTime(5.0f)));
+ public static final Block NETHER_QUARTZ_ORE = register(new Block("nether_quartz_ore", builder().requiresCorrectToolForDrops().destroyTime(3.0f)));
+ public static final Block HOPPER = register(new Block("hopper", builder().setBlockEntity(BlockEntityType.HOPPER).requiresCorrectToolForDrops().destroyTime(3.0f)
+ .booleanState(ENABLED)
+ .enumState(FACING_HOPPER, Direction.DOWN, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block QUARTZ_BLOCK = register(new Block("quartz_block", builder().requiresCorrectToolForDrops().destroyTime(0.8f)));
+ public static final Block CHISELED_QUARTZ_BLOCK = register(new Block("chiseled_quartz_block", builder().requiresCorrectToolForDrops().destroyTime(0.8f)));
+ public static final Block QUARTZ_PILLAR = register(new Block("quartz_pillar", builder().requiresCorrectToolForDrops().destroyTime(0.8f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block QUARTZ_STAIRS = register(new Block("quartz_stairs", builder().requiresCorrectToolForDrops().destroyTime(0.8f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block ACTIVATOR_RAIL = register(new Block("activator_rail", builder().destroyTime(0.7f)
+ .booleanState(POWERED)
+ .enumState(RAIL_SHAPE_STRAIGHT)
+ .booleanState(WATERLOGGED)));
+ public static final Block DROPPER = register(new Block("dropper", builder().setBlockEntity(BlockEntityType.DROPPER).requiresCorrectToolForDrops().destroyTime(3.5f)
+ .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN)
+ .booleanState(TRIGGERED)));
+ public static final Block WHITE_TERRACOTTA = register(new Block("white_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.25f)));
+ public static final Block ORANGE_TERRACOTTA = register(new Block("orange_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.25f)));
+ public static final Block MAGENTA_TERRACOTTA = register(new Block("magenta_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.25f)));
+ public static final Block LIGHT_BLUE_TERRACOTTA = register(new Block("light_blue_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.25f)));
+ public static final Block YELLOW_TERRACOTTA = register(new Block("yellow_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.25f)));
+ public static final Block LIME_TERRACOTTA = register(new Block("lime_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.25f)));
+ public static final Block PINK_TERRACOTTA = register(new Block("pink_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.25f)));
+ public static final Block GRAY_TERRACOTTA = register(new Block("gray_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.25f)));
+ public static final Block LIGHT_GRAY_TERRACOTTA = register(new Block("light_gray_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.25f)));
+ public static final Block CYAN_TERRACOTTA = register(new Block("cyan_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.25f)));
+ public static final Block PURPLE_TERRACOTTA = register(new Block("purple_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.25f)));
+ public static final Block BLUE_TERRACOTTA = register(new Block("blue_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.25f)));
+ public static final Block BROWN_TERRACOTTA = register(new Block("brown_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.25f)));
+ public static final Block GREEN_TERRACOTTA = register(new Block("green_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.25f)));
+ public static final Block RED_TERRACOTTA = register(new Block("red_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.25f)));
+ public static final Block BLACK_TERRACOTTA = register(new Block("black_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.25f)));
+ public static final Block WHITE_STAINED_GLASS_PANE = register(new Block("white_stained_glass_pane", builder().destroyTime(0.3f)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(SOUTH)
+ .booleanState(WATERLOGGED)
+ .booleanState(WEST)));
+ public static final Block ORANGE_STAINED_GLASS_PANE = register(new Block("orange_stained_glass_pane", builder().destroyTime(0.3f)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(SOUTH)
+ .booleanState(WATERLOGGED)
+ .booleanState(WEST)));
+ public static final Block MAGENTA_STAINED_GLASS_PANE = register(new Block("magenta_stained_glass_pane", builder().destroyTime(0.3f)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(SOUTH)
+ .booleanState(WATERLOGGED)
+ .booleanState(WEST)));
+ public static final Block LIGHT_BLUE_STAINED_GLASS_PANE = register(new Block("light_blue_stained_glass_pane", builder().destroyTime(0.3f)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(SOUTH)
+ .booleanState(WATERLOGGED)
+ .booleanState(WEST)));
+ public static final Block YELLOW_STAINED_GLASS_PANE = register(new Block("yellow_stained_glass_pane", builder().destroyTime(0.3f)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(SOUTH)
+ .booleanState(WATERLOGGED)
+ .booleanState(WEST)));
+ public static final Block LIME_STAINED_GLASS_PANE = register(new Block("lime_stained_glass_pane", builder().destroyTime(0.3f)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(SOUTH)
+ .booleanState(WATERLOGGED)
+ .booleanState(WEST)));
+ public static final Block PINK_STAINED_GLASS_PANE = register(new Block("pink_stained_glass_pane", builder().destroyTime(0.3f)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(SOUTH)
+ .booleanState(WATERLOGGED)
+ .booleanState(WEST)));
+ public static final Block GRAY_STAINED_GLASS_PANE = register(new Block("gray_stained_glass_pane", builder().destroyTime(0.3f)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(SOUTH)
+ .booleanState(WATERLOGGED)
+ .booleanState(WEST)));
+ public static final Block LIGHT_GRAY_STAINED_GLASS_PANE = register(new Block("light_gray_stained_glass_pane", builder().destroyTime(0.3f)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(SOUTH)
+ .booleanState(WATERLOGGED)
+ .booleanState(WEST)));
+ public static final Block CYAN_STAINED_GLASS_PANE = register(new Block("cyan_stained_glass_pane", builder().destroyTime(0.3f)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(SOUTH)
+ .booleanState(WATERLOGGED)
+ .booleanState(WEST)));
+ public static final Block PURPLE_STAINED_GLASS_PANE = register(new Block("purple_stained_glass_pane", builder().destroyTime(0.3f)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(SOUTH)
+ .booleanState(WATERLOGGED)
+ .booleanState(WEST)));
+ public static final Block BLUE_STAINED_GLASS_PANE = register(new Block("blue_stained_glass_pane", builder().destroyTime(0.3f)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(SOUTH)
+ .booleanState(WATERLOGGED)
+ .booleanState(WEST)));
+ public static final Block BROWN_STAINED_GLASS_PANE = register(new Block("brown_stained_glass_pane", builder().destroyTime(0.3f)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(SOUTH)
+ .booleanState(WATERLOGGED)
+ .booleanState(WEST)));
+ public static final Block GREEN_STAINED_GLASS_PANE = register(new Block("green_stained_glass_pane", builder().destroyTime(0.3f)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(SOUTH)
+ .booleanState(WATERLOGGED)
+ .booleanState(WEST)));
+ public static final Block RED_STAINED_GLASS_PANE = register(new Block("red_stained_glass_pane", builder().destroyTime(0.3f)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(SOUTH)
+ .booleanState(WATERLOGGED)
+ .booleanState(WEST)));
+ public static final Block BLACK_STAINED_GLASS_PANE = register(new Block("black_stained_glass_pane", builder().destroyTime(0.3f)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(SOUTH)
+ .booleanState(WATERLOGGED)
+ .booleanState(WEST)));
+ public static final Block ACACIA_STAIRS = register(new Block("acacia_stairs", builder().destroyTime(2.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block CHERRY_STAIRS = register(new Block("cherry_stairs", builder().destroyTime(2.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block DARK_OAK_STAIRS = register(new Block("dark_oak_stairs", builder().destroyTime(2.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block MANGROVE_STAIRS = register(new Block("mangrove_stairs", builder().destroyTime(2.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block BAMBOO_STAIRS = register(new Block("bamboo_stairs", builder().destroyTime(2.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block BAMBOO_MOSAIC_STAIRS = register(new Block("bamboo_mosaic_stairs", builder().destroyTime(2.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block SLIME_BLOCK = register(new Block("slime_block", builder()));
+ public static final Block BARRIER = register(new Block("barrier", builder().destroyTime(-1.0f).pushReaction(PistonBehavior.BLOCK)
+ .booleanState(WATERLOGGED)));
+ public static final Block LIGHT = register(new Block("light", builder().destroyTime(-1.0f)
+ .intState(LEVEL)
+ .booleanState(WATERLOGGED)));
+ public static final Block IRON_TRAPDOOR = register(new TrapDoorBlock("iron_trapdoor", builder().requiresCorrectToolForDrops().destroyTime(5.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .booleanState(OPEN)
+ .booleanState(POWERED)
+ .booleanState(WATERLOGGED)));
+ public static final Block PRISMARINE = register(new Block("prismarine", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
+ public static final Block PRISMARINE_BRICKS = register(new Block("prismarine_bricks", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
+ public static final Block DARK_PRISMARINE = register(new Block("dark_prismarine", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
+ public static final Block PRISMARINE_STAIRS = register(new Block("prismarine_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block PRISMARINE_BRICK_STAIRS = register(new Block("prismarine_brick_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block DARK_PRISMARINE_STAIRS = register(new Block("dark_prismarine_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block PRISMARINE_SLAB = register(new Block("prismarine_slab", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block PRISMARINE_BRICK_SLAB = register(new Block("prismarine_brick_slab", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block DARK_PRISMARINE_SLAB = register(new Block("dark_prismarine_slab", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block SEA_LANTERN = register(new Block("sea_lantern", builder().destroyTime(0.3f)));
+ public static final Block HAY_BLOCK = register(new Block("hay_block", builder().destroyTime(0.5f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block WHITE_CARPET = register(new Block("white_carpet", builder().destroyTime(0.1f)));
+ public static final Block ORANGE_CARPET = register(new Block("orange_carpet", builder().destroyTime(0.1f)));
+ public static final Block MAGENTA_CARPET = register(new Block("magenta_carpet", builder().destroyTime(0.1f)));
+ public static final Block LIGHT_BLUE_CARPET = register(new Block("light_blue_carpet", builder().destroyTime(0.1f)));
+ public static final Block YELLOW_CARPET = register(new Block("yellow_carpet", builder().destroyTime(0.1f)));
+ public static final Block LIME_CARPET = register(new Block("lime_carpet", builder().destroyTime(0.1f)));
+ public static final Block PINK_CARPET = register(new Block("pink_carpet", builder().destroyTime(0.1f)));
+ public static final Block GRAY_CARPET = register(new Block("gray_carpet", builder().destroyTime(0.1f)));
+ public static final Block LIGHT_GRAY_CARPET = register(new Block("light_gray_carpet", builder().destroyTime(0.1f)));
+ public static final Block CYAN_CARPET = register(new Block("cyan_carpet", builder().destroyTime(0.1f)));
+ public static final Block PURPLE_CARPET = register(new Block("purple_carpet", builder().destroyTime(0.1f)));
+ public static final Block BLUE_CARPET = register(new Block("blue_carpet", builder().destroyTime(0.1f)));
+ public static final Block BROWN_CARPET = register(new Block("brown_carpet", builder().destroyTime(0.1f)));
+ public static final Block GREEN_CARPET = register(new Block("green_carpet", builder().destroyTime(0.1f)));
+ public static final Block RED_CARPET = register(new Block("red_carpet", builder().destroyTime(0.1f)));
+ public static final Block BLACK_CARPET = register(new Block("black_carpet", builder().destroyTime(0.1f)));
+ public static final Block TERRACOTTA = register(new Block("terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.25f)));
+ public static final Block COAL_BLOCK = register(new Block("coal_block", builder().requiresCorrectToolForDrops().destroyTime(5.0f)));
+ public static final Block PACKED_ICE = register(new Block("packed_ice", builder().destroyTime(0.5f)));
+ public static final Block SUNFLOWER = register(new Block("sunflower", builder().pushReaction(PistonBehavior.DESTROY)
+ .enumState(DOUBLE_BLOCK_HALF)));
+ public static final Block LILAC = register(new Block("lilac", builder().pushReaction(PistonBehavior.DESTROY)
+ .enumState(DOUBLE_BLOCK_HALF)));
+ public static final Block ROSE_BUSH = register(new Block("rose_bush", builder().pushReaction(PistonBehavior.DESTROY)
+ .enumState(DOUBLE_BLOCK_HALF)));
+ public static final Block PEONY = register(new Block("peony", builder().pushReaction(PistonBehavior.DESTROY)
+ .enumState(DOUBLE_BLOCK_HALF)));
+ public static final Block TALL_GRASS = register(new Block("tall_grass", builder().pushReaction(PistonBehavior.DESTROY)
+ .enumState(DOUBLE_BLOCK_HALF)));
+ public static final Block LARGE_FERN = register(new Block("large_fern", builder().pushReaction(PistonBehavior.DESTROY)
+ .enumState(DOUBLE_BLOCK_HALF)));
+ public static final Block WHITE_BANNER = register(new BannerBlock("white_banner", 0, builder().setBlockEntity(BlockEntityType.BANNER).destroyTime(1.0f)
+ .intState(ROTATION_16)));
+ public static final Block ORANGE_BANNER = register(new BannerBlock("orange_banner", 1, builder().setBlockEntity(BlockEntityType.BANNER).destroyTime(1.0f)
+ .intState(ROTATION_16)));
+ public static final Block MAGENTA_BANNER = register(new BannerBlock("magenta_banner", 2, builder().setBlockEntity(BlockEntityType.BANNER).destroyTime(1.0f)
+ .intState(ROTATION_16)));
+ public static final Block LIGHT_BLUE_BANNER = register(new BannerBlock("light_blue_banner", 3, builder().setBlockEntity(BlockEntityType.BANNER).destroyTime(1.0f)
+ .intState(ROTATION_16)));
+ public static final Block YELLOW_BANNER = register(new BannerBlock("yellow_banner", 4, builder().setBlockEntity(BlockEntityType.BANNER).destroyTime(1.0f)
+ .intState(ROTATION_16)));
+ public static final Block LIME_BANNER = register(new BannerBlock("lime_banner", 5, builder().setBlockEntity(BlockEntityType.BANNER).destroyTime(1.0f)
+ .intState(ROTATION_16)));
+ public static final Block PINK_BANNER = register(new BannerBlock("pink_banner", 6, builder().setBlockEntity(BlockEntityType.BANNER).destroyTime(1.0f)
+ .intState(ROTATION_16)));
+ public static final Block GRAY_BANNER = register(new BannerBlock("gray_banner", 7, builder().setBlockEntity(BlockEntityType.BANNER).destroyTime(1.0f)
+ .intState(ROTATION_16)));
+ public static final Block LIGHT_GRAY_BANNER = register(new BannerBlock("light_gray_banner", 8, builder().setBlockEntity(BlockEntityType.BANNER).destroyTime(1.0f)
+ .intState(ROTATION_16)));
+ public static final Block CYAN_BANNER = register(new BannerBlock("cyan_banner", 9, builder().setBlockEntity(BlockEntityType.BANNER).destroyTime(1.0f)
+ .intState(ROTATION_16)));
+ public static final Block PURPLE_BANNER = register(new BannerBlock("purple_banner", 10, builder().setBlockEntity(BlockEntityType.BANNER).destroyTime(1.0f)
+ .intState(ROTATION_16)));
+ public static final Block BLUE_BANNER = register(new BannerBlock("blue_banner", 11, builder().setBlockEntity(BlockEntityType.BANNER).destroyTime(1.0f)
+ .intState(ROTATION_16)));
+ public static final Block BROWN_BANNER = register(new BannerBlock("brown_banner", 12, builder().setBlockEntity(BlockEntityType.BANNER).destroyTime(1.0f)
+ .intState(ROTATION_16)));
+ public static final Block GREEN_BANNER = register(new BannerBlock("green_banner", 13, builder().setBlockEntity(BlockEntityType.BANNER).destroyTime(1.0f)
+ .intState(ROTATION_16)));
+ public static final Block RED_BANNER = register(new BannerBlock("red_banner", 14, builder().setBlockEntity(BlockEntityType.BANNER).destroyTime(1.0f)
+ .intState(ROTATION_16)));
+ public static final Block BLACK_BANNER = register(new BannerBlock("black_banner", 15, builder().setBlockEntity(BlockEntityType.BANNER).destroyTime(1.0f)
+ .intState(ROTATION_16)));
+ public static final Block WHITE_WALL_BANNER = register(new BannerBlock("white_wall_banner", 0, builder().setBlockEntity(BlockEntityType.BANNER).destroyTime(1.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block ORANGE_WALL_BANNER = register(new BannerBlock("orange_wall_banner", 1, builder().setBlockEntity(BlockEntityType.BANNER).destroyTime(1.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block MAGENTA_WALL_BANNER = register(new BannerBlock("magenta_wall_banner", 2, builder().setBlockEntity(BlockEntityType.BANNER).destroyTime(1.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block LIGHT_BLUE_WALL_BANNER = register(new BannerBlock("light_blue_wall_banner", 3, builder().setBlockEntity(BlockEntityType.BANNER).destroyTime(1.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block YELLOW_WALL_BANNER = register(new BannerBlock("yellow_wall_banner", 4, builder().setBlockEntity(BlockEntityType.BANNER).destroyTime(1.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block LIME_WALL_BANNER = register(new BannerBlock("lime_wall_banner", 5, builder().setBlockEntity(BlockEntityType.BANNER).destroyTime(1.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block PINK_WALL_BANNER = register(new BannerBlock("pink_wall_banner", 6, builder().setBlockEntity(BlockEntityType.BANNER).destroyTime(1.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block GRAY_WALL_BANNER = register(new BannerBlock("gray_wall_banner", 7, builder().setBlockEntity(BlockEntityType.BANNER).destroyTime(1.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block LIGHT_GRAY_WALL_BANNER = register(new BannerBlock("light_gray_wall_banner", 8, builder().setBlockEntity(BlockEntityType.BANNER).destroyTime(1.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block CYAN_WALL_BANNER = register(new BannerBlock("cyan_wall_banner", 9, builder().setBlockEntity(BlockEntityType.BANNER).destroyTime(1.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block PURPLE_WALL_BANNER = register(new BannerBlock("purple_wall_banner", 10, builder().setBlockEntity(BlockEntityType.BANNER).destroyTime(1.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block BLUE_WALL_BANNER = register(new BannerBlock("blue_wall_banner", 11, builder().setBlockEntity(BlockEntityType.BANNER).destroyTime(1.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block BROWN_WALL_BANNER = register(new BannerBlock("brown_wall_banner", 12, builder().setBlockEntity(BlockEntityType.BANNER).destroyTime(1.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block GREEN_WALL_BANNER = register(new BannerBlock("green_wall_banner", 13, builder().setBlockEntity(BlockEntityType.BANNER).destroyTime(1.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block RED_WALL_BANNER = register(new BannerBlock("red_wall_banner", 14, builder().setBlockEntity(BlockEntityType.BANNER).destroyTime(1.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block BLACK_WALL_BANNER = register(new BannerBlock("black_wall_banner", 15, builder().setBlockEntity(BlockEntityType.BANNER).destroyTime(1.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block RED_SANDSTONE = register(new Block("red_sandstone", builder().requiresCorrectToolForDrops().destroyTime(0.8f)));
+ public static final Block CHISELED_RED_SANDSTONE = register(new Block("chiseled_red_sandstone", builder().requiresCorrectToolForDrops().destroyTime(0.8f)));
+ public static final Block CUT_RED_SANDSTONE = register(new Block("cut_red_sandstone", builder().requiresCorrectToolForDrops().destroyTime(0.8f)));
+ public static final Block RED_SANDSTONE_STAIRS = register(new Block("red_sandstone_stairs", builder().requiresCorrectToolForDrops().destroyTime(0.8f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block OAK_SLAB = register(new Block("oak_slab", builder().destroyTime(2.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block SPRUCE_SLAB = register(new Block("spruce_slab", builder().destroyTime(2.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block BIRCH_SLAB = register(new Block("birch_slab", builder().destroyTime(2.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block JUNGLE_SLAB = register(new Block("jungle_slab", builder().destroyTime(2.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block ACACIA_SLAB = register(new Block("acacia_slab", builder().destroyTime(2.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block CHERRY_SLAB = register(new Block("cherry_slab", builder().destroyTime(2.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block DARK_OAK_SLAB = register(new Block("dark_oak_slab", builder().destroyTime(2.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block MANGROVE_SLAB = register(new Block("mangrove_slab", builder().destroyTime(2.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block BAMBOO_SLAB = register(new Block("bamboo_slab", builder().destroyTime(2.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block BAMBOO_MOSAIC_SLAB = register(new Block("bamboo_mosaic_slab", builder().destroyTime(2.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block STONE_SLAB = register(new Block("stone_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block SMOOTH_STONE_SLAB = register(new Block("smooth_stone_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block SANDSTONE_SLAB = register(new Block("sandstone_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block CUT_SANDSTONE_SLAB = register(new Block("cut_sandstone_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block PETRIFIED_OAK_SLAB = register(new Block("petrified_oak_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block COBBLESTONE_SLAB = register(new Block("cobblestone_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block BRICK_SLAB = register(new Block("brick_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block STONE_BRICK_SLAB = register(new Block("stone_brick_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block MUD_BRICK_SLAB = register(new Block("mud_brick_slab", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block NETHER_BRICK_SLAB = register(new Block("nether_brick_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block QUARTZ_SLAB = register(new Block("quartz_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block RED_SANDSTONE_SLAB = register(new Block("red_sandstone_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block CUT_RED_SANDSTONE_SLAB = register(new Block("cut_red_sandstone_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block PURPUR_SLAB = register(new Block("purpur_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block SMOOTH_STONE = register(new Block("smooth_stone", builder().requiresCorrectToolForDrops().destroyTime(2.0f)));
+ public static final Block SMOOTH_SANDSTONE = register(new Block("smooth_sandstone", builder().requiresCorrectToolForDrops().destroyTime(2.0f)));
+ public static final Block SMOOTH_QUARTZ = register(new Block("smooth_quartz", builder().requiresCorrectToolForDrops().destroyTime(2.0f)));
+ public static final Block SMOOTH_RED_SANDSTONE = register(new Block("smooth_red_sandstone", builder().requiresCorrectToolForDrops().destroyTime(2.0f)));
+ public static final Block SPRUCE_FENCE_GATE = register(new Block("spruce_fence_gate", builder().destroyTime(2.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(IN_WALL)
+ .booleanState(OPEN)
+ .booleanState(POWERED)));
+ public static final Block BIRCH_FENCE_GATE = register(new Block("birch_fence_gate", builder().destroyTime(2.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(IN_WALL)
+ .booleanState(OPEN)
+ .booleanState(POWERED)));
+ public static final Block JUNGLE_FENCE_GATE = register(new Block("jungle_fence_gate", builder().destroyTime(2.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(IN_WALL)
+ .booleanState(OPEN)
+ .booleanState(POWERED)));
+ public static final Block ACACIA_FENCE_GATE = register(new Block("acacia_fence_gate", builder().destroyTime(2.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(IN_WALL)
+ .booleanState(OPEN)
+ .booleanState(POWERED)));
+ public static final Block CHERRY_FENCE_GATE = register(new Block("cherry_fence_gate", builder().destroyTime(2.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(IN_WALL)
+ .booleanState(OPEN)
+ .booleanState(POWERED)));
+ public static final Block DARK_OAK_FENCE_GATE = register(new Block("dark_oak_fence_gate", builder().destroyTime(2.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(IN_WALL)
+ .booleanState(OPEN)
+ .booleanState(POWERED)));
+ public static final Block MANGROVE_FENCE_GATE = register(new Block("mangrove_fence_gate", builder().destroyTime(2.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(IN_WALL)
+ .booleanState(OPEN)
+ .booleanState(POWERED)));
+ public static final Block BAMBOO_FENCE_GATE = register(new Block("bamboo_fence_gate", builder().destroyTime(2.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(IN_WALL)
+ .booleanState(OPEN)
+ .booleanState(POWERED)));
+ public static final Block SPRUCE_FENCE = register(new Block("spruce_fence", builder().destroyTime(2.0f)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(SOUTH)
+ .booleanState(WATERLOGGED)
+ .booleanState(WEST)));
+ public static final Block BIRCH_FENCE = register(new Block("birch_fence", builder().destroyTime(2.0f)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(SOUTH)
+ .booleanState(WATERLOGGED)
+ .booleanState(WEST)));
+ public static final Block JUNGLE_FENCE = register(new Block("jungle_fence", builder().destroyTime(2.0f)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(SOUTH)
+ .booleanState(WATERLOGGED)
+ .booleanState(WEST)));
+ public static final Block ACACIA_FENCE = register(new Block("acacia_fence", builder().destroyTime(2.0f)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(SOUTH)
+ .booleanState(WATERLOGGED)
+ .booleanState(WEST)));
+ public static final Block CHERRY_FENCE = register(new Block("cherry_fence", builder().destroyTime(2.0f)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(SOUTH)
+ .booleanState(WATERLOGGED)
+ .booleanState(WEST)));
+ public static final Block DARK_OAK_FENCE = register(new Block("dark_oak_fence", builder().destroyTime(2.0f)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(SOUTH)
+ .booleanState(WATERLOGGED)
+ .booleanState(WEST)));
+ public static final Block MANGROVE_FENCE = register(new Block("mangrove_fence", builder().destroyTime(2.0f)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(SOUTH)
+ .booleanState(WATERLOGGED)
+ .booleanState(WEST)));
+ public static final Block BAMBOO_FENCE = register(new Block("bamboo_fence", builder().destroyTime(2.0f)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(SOUTH)
+ .booleanState(WATERLOGGED)
+ .booleanState(WEST)));
+ public static final Block SPRUCE_DOOR = register(new DoorBlock("spruce_door", builder().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(DOUBLE_BLOCK_HALF)
+ .enumState(DOOR_HINGE)
+ .booleanState(OPEN)
+ .booleanState(POWERED)));
+ public static final Block BIRCH_DOOR = register(new DoorBlock("birch_door", builder().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(DOUBLE_BLOCK_HALF)
+ .enumState(DOOR_HINGE)
+ .booleanState(OPEN)
+ .booleanState(POWERED)));
+ public static final Block JUNGLE_DOOR = register(new DoorBlock("jungle_door", builder().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(DOUBLE_BLOCK_HALF)
+ .enumState(DOOR_HINGE)
+ .booleanState(OPEN)
+ .booleanState(POWERED)));
+ public static final Block ACACIA_DOOR = register(new DoorBlock("acacia_door", builder().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(DOUBLE_BLOCK_HALF)
+ .enumState(DOOR_HINGE)
+ .booleanState(OPEN)
+ .booleanState(POWERED)));
+ public static final Block CHERRY_DOOR = register(new DoorBlock("cherry_door", builder().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(DOUBLE_BLOCK_HALF)
+ .enumState(DOOR_HINGE)
+ .booleanState(OPEN)
+ .booleanState(POWERED)));
+ public static final Block DARK_OAK_DOOR = register(new DoorBlock("dark_oak_door", builder().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(DOUBLE_BLOCK_HALF)
+ .enumState(DOOR_HINGE)
+ .booleanState(OPEN)
+ .booleanState(POWERED)));
+ public static final Block MANGROVE_DOOR = register(new DoorBlock("mangrove_door", builder().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(DOUBLE_BLOCK_HALF)
+ .enumState(DOOR_HINGE)
+ .booleanState(OPEN)
+ .booleanState(POWERED)));
+ public static final Block BAMBOO_DOOR = register(new DoorBlock("bamboo_door", builder().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(DOUBLE_BLOCK_HALF)
+ .enumState(DOOR_HINGE)
+ .booleanState(OPEN)
+ .booleanState(POWERED)));
+ public static final Block END_ROD = register(new Block("end_rod", builder()
+ .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN)));
+ public static final Block CHORUS_PLANT = register(new Block("chorus_plant", builder().destroyTime(0.4f).pushReaction(PistonBehavior.DESTROY)
+ .booleanState(DOWN)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(SOUTH)
+ .booleanState(UP)
+ .booleanState(WEST)));
+ public static final Block CHORUS_FLOWER = register(new Block("chorus_flower", builder().destroyTime(0.4f).pushReaction(PistonBehavior.DESTROY)
+ .intState(AGE_5)));
+ public static final Block PURPUR_BLOCK = register(new Block("purpur_block", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
+ public static final Block PURPUR_PILLAR = register(new Block("purpur_pillar", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block PURPUR_STAIRS = register(new Block("purpur_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block END_STONE_BRICKS = register(new Block("end_stone_bricks", builder().requiresCorrectToolForDrops().destroyTime(3.0f)));
+ public static final Block TORCHFLOWER_CROP = register(new Block("torchflower_crop", builder().pushReaction(PistonBehavior.DESTROY)
+ .intState(AGE_1)));
+ public static final Block PITCHER_CROP = register(new Block("pitcher_crop", builder().pushReaction(PistonBehavior.DESTROY)
+ .intState(AGE_4)
+ .enumState(DOUBLE_BLOCK_HALF)));
+ public static final Block PITCHER_PLANT = register(new Block("pitcher_plant", builder().pushReaction(PistonBehavior.DESTROY)
+ .enumState(DOUBLE_BLOCK_HALF)));
+ public static final Block BEETROOTS = register(new Block("beetroots", builder().pushReaction(PistonBehavior.DESTROY)
+ .intState(AGE_3)));
+ public static final Block DIRT_PATH = register(new Block("dirt_path", builder().destroyTime(0.65f)));
+ public static final Block END_GATEWAY = register(new Block("end_gateway", builder().setBlockEntity(BlockEntityType.END_GATEWAY).destroyTime(-1.0f).pushReaction(PistonBehavior.BLOCK)));
+ public static final Block REPEATING_COMMAND_BLOCK = register(new Block("repeating_command_block", builder().setBlockEntity(BlockEntityType.COMMAND_BLOCK).requiresCorrectToolForDrops().destroyTime(-1.0f)
+ .booleanState(CONDITIONAL)
+ .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN)));
+ public static final Block CHAIN_COMMAND_BLOCK = register(new Block("chain_command_block", builder().setBlockEntity(BlockEntityType.COMMAND_BLOCK).requiresCorrectToolForDrops().destroyTime(-1.0f)
+ .booleanState(CONDITIONAL)
+ .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN)));
+ public static final Block FROSTED_ICE = register(new Block("frosted_ice", builder().destroyTime(0.5f)
+ .intState(AGE_3)));
+ public static final Block MAGMA_BLOCK = register(new Block("magma_block", builder().requiresCorrectToolForDrops().destroyTime(0.5f)));
+ public static final Block NETHER_WART_BLOCK = register(new Block("nether_wart_block", builder().destroyTime(1.0f)));
+ public static final Block RED_NETHER_BRICKS = register(new Block("red_nether_bricks", builder().requiresCorrectToolForDrops().destroyTime(2.0f)));
+ public static final Block BONE_BLOCK = register(new Block("bone_block", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block STRUCTURE_VOID = register(new Block("structure_void", builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block OBSERVER = register(new Block("observer", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN)
+ .booleanState(POWERED)));
+ public static final Block SHULKER_BOX = register(new Block("shulker_box", builder().setBlockEntity(BlockEntityType.SHULKER_BOX).destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN)));
+ public static final Block WHITE_SHULKER_BOX = register(new Block("white_shulker_box", builder().setBlockEntity(BlockEntityType.SHULKER_BOX).destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN)));
+ public static final Block ORANGE_SHULKER_BOX = register(new Block("orange_shulker_box", builder().setBlockEntity(BlockEntityType.SHULKER_BOX).destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN)));
+ public static final Block MAGENTA_SHULKER_BOX = register(new Block("magenta_shulker_box", builder().setBlockEntity(BlockEntityType.SHULKER_BOX).destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN)));
+ public static final Block LIGHT_BLUE_SHULKER_BOX = register(new Block("light_blue_shulker_box", builder().setBlockEntity(BlockEntityType.SHULKER_BOX).destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN)));
+ public static final Block YELLOW_SHULKER_BOX = register(new Block("yellow_shulker_box", builder().setBlockEntity(BlockEntityType.SHULKER_BOX).destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN)));
+ public static final Block LIME_SHULKER_BOX = register(new Block("lime_shulker_box", builder().setBlockEntity(BlockEntityType.SHULKER_BOX).destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN)));
+ public static final Block PINK_SHULKER_BOX = register(new Block("pink_shulker_box", builder().setBlockEntity(BlockEntityType.SHULKER_BOX).destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN)));
+ public static final Block GRAY_SHULKER_BOX = register(new Block("gray_shulker_box", builder().setBlockEntity(BlockEntityType.SHULKER_BOX).destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN)));
+ public static final Block LIGHT_GRAY_SHULKER_BOX = register(new Block("light_gray_shulker_box", builder().setBlockEntity(BlockEntityType.SHULKER_BOX).destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN)));
+ public static final Block CYAN_SHULKER_BOX = register(new Block("cyan_shulker_box", builder().setBlockEntity(BlockEntityType.SHULKER_BOX).destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN)));
+ public static final Block PURPLE_SHULKER_BOX = register(new Block("purple_shulker_box", builder().setBlockEntity(BlockEntityType.SHULKER_BOX).destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN)));
+ public static final Block BLUE_SHULKER_BOX = register(new Block("blue_shulker_box", builder().setBlockEntity(BlockEntityType.SHULKER_BOX).destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN)));
+ public static final Block BROWN_SHULKER_BOX = register(new Block("brown_shulker_box", builder().setBlockEntity(BlockEntityType.SHULKER_BOX).destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN)));
+ public static final Block GREEN_SHULKER_BOX = register(new Block("green_shulker_box", builder().setBlockEntity(BlockEntityType.SHULKER_BOX).destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN)));
+ public static final Block RED_SHULKER_BOX = register(new Block("red_shulker_box", builder().setBlockEntity(BlockEntityType.SHULKER_BOX).destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN)));
+ public static final Block BLACK_SHULKER_BOX = register(new Block("black_shulker_box", builder().setBlockEntity(BlockEntityType.SHULKER_BOX).destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN)));
+ public static final Block WHITE_GLAZED_TERRACOTTA = register(new Block("white_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f).pushReaction(PistonBehavior.PUSH_ONLY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block ORANGE_GLAZED_TERRACOTTA = register(new Block("orange_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f).pushReaction(PistonBehavior.PUSH_ONLY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block MAGENTA_GLAZED_TERRACOTTA = register(new Block("magenta_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f).pushReaction(PistonBehavior.PUSH_ONLY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block LIGHT_BLUE_GLAZED_TERRACOTTA = register(new Block("light_blue_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f).pushReaction(PistonBehavior.PUSH_ONLY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block YELLOW_GLAZED_TERRACOTTA = register(new Block("yellow_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f).pushReaction(PistonBehavior.PUSH_ONLY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block LIME_GLAZED_TERRACOTTA = register(new Block("lime_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f).pushReaction(PistonBehavior.PUSH_ONLY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block PINK_GLAZED_TERRACOTTA = register(new Block("pink_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f).pushReaction(PistonBehavior.PUSH_ONLY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block GRAY_GLAZED_TERRACOTTA = register(new Block("gray_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f).pushReaction(PistonBehavior.PUSH_ONLY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block LIGHT_GRAY_GLAZED_TERRACOTTA = register(new Block("light_gray_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f).pushReaction(PistonBehavior.PUSH_ONLY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block CYAN_GLAZED_TERRACOTTA = register(new Block("cyan_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f).pushReaction(PistonBehavior.PUSH_ONLY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block PURPLE_GLAZED_TERRACOTTA = register(new Block("purple_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f).pushReaction(PistonBehavior.PUSH_ONLY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block BLUE_GLAZED_TERRACOTTA = register(new Block("blue_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f).pushReaction(PistonBehavior.PUSH_ONLY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block BROWN_GLAZED_TERRACOTTA = register(new Block("brown_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f).pushReaction(PistonBehavior.PUSH_ONLY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block GREEN_GLAZED_TERRACOTTA = register(new Block("green_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f).pushReaction(PistonBehavior.PUSH_ONLY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block RED_GLAZED_TERRACOTTA = register(new Block("red_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f).pushReaction(PistonBehavior.PUSH_ONLY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block BLACK_GLAZED_TERRACOTTA = register(new Block("black_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f).pushReaction(PistonBehavior.PUSH_ONLY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block WHITE_CONCRETE = register(new Block("white_concrete", builder().requiresCorrectToolForDrops().destroyTime(1.8f)));
+ public static final Block ORANGE_CONCRETE = register(new Block("orange_concrete", builder().requiresCorrectToolForDrops().destroyTime(1.8f)));
+ public static final Block MAGENTA_CONCRETE = register(new Block("magenta_concrete", builder().requiresCorrectToolForDrops().destroyTime(1.8f)));
+ public static final Block LIGHT_BLUE_CONCRETE = register(new Block("light_blue_concrete", builder().requiresCorrectToolForDrops().destroyTime(1.8f)));
+ public static final Block YELLOW_CONCRETE = register(new Block("yellow_concrete", builder().requiresCorrectToolForDrops().destroyTime(1.8f)));
+ public static final Block LIME_CONCRETE = register(new Block("lime_concrete", builder().requiresCorrectToolForDrops().destroyTime(1.8f)));
+ public static final Block PINK_CONCRETE = register(new Block("pink_concrete", builder().requiresCorrectToolForDrops().destroyTime(1.8f)));
+ public static final Block GRAY_CONCRETE = register(new Block("gray_concrete", builder().requiresCorrectToolForDrops().destroyTime(1.8f)));
+ public static final Block LIGHT_GRAY_CONCRETE = register(new Block("light_gray_concrete", builder().requiresCorrectToolForDrops().destroyTime(1.8f)));
+ public static final Block CYAN_CONCRETE = register(new Block("cyan_concrete", builder().requiresCorrectToolForDrops().destroyTime(1.8f)));
+ public static final Block PURPLE_CONCRETE = register(new Block("purple_concrete", builder().requiresCorrectToolForDrops().destroyTime(1.8f)));
+ public static final Block BLUE_CONCRETE = register(new Block("blue_concrete", builder().requiresCorrectToolForDrops().destroyTime(1.8f)));
+ public static final Block BROWN_CONCRETE = register(new Block("brown_concrete", builder().requiresCorrectToolForDrops().destroyTime(1.8f)));
+ public static final Block GREEN_CONCRETE = register(new Block("green_concrete", builder().requiresCorrectToolForDrops().destroyTime(1.8f)));
+ public static final Block RED_CONCRETE = register(new Block("red_concrete", builder().requiresCorrectToolForDrops().destroyTime(1.8f)));
+ public static final Block BLACK_CONCRETE = register(new Block("black_concrete", builder().requiresCorrectToolForDrops().destroyTime(1.8f)));
+ public static final Block WHITE_CONCRETE_POWDER = register(new Block("white_concrete_powder", builder().destroyTime(0.5f)));
+ public static final Block ORANGE_CONCRETE_POWDER = register(new Block("orange_concrete_powder", builder().destroyTime(0.5f)));
+ public static final Block MAGENTA_CONCRETE_POWDER = register(new Block("magenta_concrete_powder", builder().destroyTime(0.5f)));
+ public static final Block LIGHT_BLUE_CONCRETE_POWDER = register(new Block("light_blue_concrete_powder", builder().destroyTime(0.5f)));
+ public static final Block YELLOW_CONCRETE_POWDER = register(new Block("yellow_concrete_powder", builder().destroyTime(0.5f)));
+ public static final Block LIME_CONCRETE_POWDER = register(new Block("lime_concrete_powder", builder().destroyTime(0.5f)));
+ public static final Block PINK_CONCRETE_POWDER = register(new Block("pink_concrete_powder", builder().destroyTime(0.5f)));
+ public static final Block GRAY_CONCRETE_POWDER = register(new Block("gray_concrete_powder", builder().destroyTime(0.5f)));
+ public static final Block LIGHT_GRAY_CONCRETE_POWDER = register(new Block("light_gray_concrete_powder", builder().destroyTime(0.5f)));
+ public static final Block CYAN_CONCRETE_POWDER = register(new Block("cyan_concrete_powder", builder().destroyTime(0.5f)));
+ public static final Block PURPLE_CONCRETE_POWDER = register(new Block("purple_concrete_powder", builder().destroyTime(0.5f)));
+ public static final Block BLUE_CONCRETE_POWDER = register(new Block("blue_concrete_powder", builder().destroyTime(0.5f)));
+ public static final Block BROWN_CONCRETE_POWDER = register(new Block("brown_concrete_powder", builder().destroyTime(0.5f)));
+ public static final Block GREEN_CONCRETE_POWDER = register(new Block("green_concrete_powder", builder().destroyTime(0.5f)));
+ public static final Block RED_CONCRETE_POWDER = register(new Block("red_concrete_powder", builder().destroyTime(0.5f)));
+ public static final Block BLACK_CONCRETE_POWDER = register(new Block("black_concrete_powder", builder().destroyTime(0.5f)));
+ public static final Block KELP = register(new Block("kelp", builder().pushReaction(PistonBehavior.DESTROY)
+ .intState(AGE_25)));
+ public static final Block KELP_PLANT = register(new Block("kelp_plant", builder().pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.KELP)));
+ public static final Block DRIED_KELP_BLOCK = register(new Block("dried_kelp_block", builder().destroyTime(0.5f)));
+ public static final Block TURTLE_EGG = register(new Block("turtle_egg", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY)
+ .intState(EGGS)
+ .intState(HATCH)));
+ public static final Block SNIFFER_EGG = register(new Block("sniffer_egg", builder().destroyTime(0.5f)
+ .intState(HATCH)));
+ public static final Block DEAD_TUBE_CORAL_BLOCK = register(new Block("dead_tube_coral_block", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
+ public static final Block DEAD_BRAIN_CORAL_BLOCK = register(new Block("dead_brain_coral_block", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
+ public static final Block DEAD_BUBBLE_CORAL_BLOCK = register(new Block("dead_bubble_coral_block", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
+ public static final Block DEAD_FIRE_CORAL_BLOCK = register(new Block("dead_fire_coral_block", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
+ public static final Block DEAD_HORN_CORAL_BLOCK = register(new Block("dead_horn_coral_block", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
+ public static final Block TUBE_CORAL_BLOCK = register(new Block("tube_coral_block", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
+ public static final Block BRAIN_CORAL_BLOCK = register(new Block("brain_coral_block", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
+ public static final Block BUBBLE_CORAL_BLOCK = register(new Block("bubble_coral_block", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
+ public static final Block FIRE_CORAL_BLOCK = register(new Block("fire_coral_block", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
+ public static final Block HORN_CORAL_BLOCK = register(new Block("horn_coral_block", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
+ public static final Block DEAD_TUBE_CORAL = register(new Block("dead_tube_coral", builder().requiresCorrectToolForDrops()
+ .booleanState(WATERLOGGED)));
+ public static final Block DEAD_BRAIN_CORAL = register(new Block("dead_brain_coral", builder().requiresCorrectToolForDrops()
+ .booleanState(WATERLOGGED)));
+ public static final Block DEAD_BUBBLE_CORAL = register(new Block("dead_bubble_coral", builder().requiresCorrectToolForDrops()
+ .booleanState(WATERLOGGED)));
+ public static final Block DEAD_FIRE_CORAL = register(new Block("dead_fire_coral", builder().requiresCorrectToolForDrops()
+ .booleanState(WATERLOGGED)));
+ public static final Block DEAD_HORN_CORAL = register(new Block("dead_horn_coral", builder().requiresCorrectToolForDrops()
+ .booleanState(WATERLOGGED)));
+ public static final Block TUBE_CORAL = register(new Block("tube_coral", builder().pushReaction(PistonBehavior.DESTROY)
+ .booleanState(WATERLOGGED)));
+ public static final Block BRAIN_CORAL = register(new Block("brain_coral", builder().pushReaction(PistonBehavior.DESTROY)
+ .booleanState(WATERLOGGED)));
+ public static final Block BUBBLE_CORAL = register(new Block("bubble_coral", builder().pushReaction(PistonBehavior.DESTROY)
+ .booleanState(WATERLOGGED)));
+ public static final Block FIRE_CORAL = register(new Block("fire_coral", builder().pushReaction(PistonBehavior.DESTROY)
+ .booleanState(WATERLOGGED)));
+ public static final Block HORN_CORAL = register(new Block("horn_coral", builder().pushReaction(PistonBehavior.DESTROY)
+ .booleanState(WATERLOGGED)));
+ public static final Block DEAD_TUBE_CORAL_FAN = register(new Block("dead_tube_coral_fan", builder().requiresCorrectToolForDrops()
+ .booleanState(WATERLOGGED)));
+ public static final Block DEAD_BRAIN_CORAL_FAN = register(new Block("dead_brain_coral_fan", builder().requiresCorrectToolForDrops()
+ .booleanState(WATERLOGGED)));
+ public static final Block DEAD_BUBBLE_CORAL_FAN = register(new Block("dead_bubble_coral_fan", builder().requiresCorrectToolForDrops()
+ .booleanState(WATERLOGGED)));
+ public static final Block DEAD_FIRE_CORAL_FAN = register(new Block("dead_fire_coral_fan", builder().requiresCorrectToolForDrops()
+ .booleanState(WATERLOGGED)));
+ public static final Block DEAD_HORN_CORAL_FAN = register(new Block("dead_horn_coral_fan", builder().requiresCorrectToolForDrops()
+ .booleanState(WATERLOGGED)));
+ public static final Block TUBE_CORAL_FAN = register(new Block("tube_coral_fan", builder().pushReaction(PistonBehavior.DESTROY)
+ .booleanState(WATERLOGGED)));
+ public static final Block BRAIN_CORAL_FAN = register(new Block("brain_coral_fan", builder().pushReaction(PistonBehavior.DESTROY)
+ .booleanState(WATERLOGGED)));
+ public static final Block BUBBLE_CORAL_FAN = register(new Block("bubble_coral_fan", builder().pushReaction(PistonBehavior.DESTROY)
+ .booleanState(WATERLOGGED)));
+ public static final Block FIRE_CORAL_FAN = register(new Block("fire_coral_fan", builder().pushReaction(PistonBehavior.DESTROY)
+ .booleanState(WATERLOGGED)));
+ public static final Block HORN_CORAL_FAN = register(new Block("horn_coral_fan", builder().pushReaction(PistonBehavior.DESTROY)
+ .booleanState(WATERLOGGED)));
+ public static final Block DEAD_TUBE_CORAL_WALL_FAN = register(new Block("dead_tube_coral_wall_fan", builder().requiresCorrectToolForDrops()
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(WATERLOGGED)));
+ public static final Block DEAD_BRAIN_CORAL_WALL_FAN = register(new Block("dead_brain_coral_wall_fan", builder().requiresCorrectToolForDrops()
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(WATERLOGGED)));
+ public static final Block DEAD_BUBBLE_CORAL_WALL_FAN = register(new Block("dead_bubble_coral_wall_fan", builder().requiresCorrectToolForDrops()
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(WATERLOGGED)));
+ public static final Block DEAD_FIRE_CORAL_WALL_FAN = register(new Block("dead_fire_coral_wall_fan", builder().requiresCorrectToolForDrops()
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(WATERLOGGED)));
+ public static final Block DEAD_HORN_CORAL_WALL_FAN = register(new Block("dead_horn_coral_wall_fan", builder().requiresCorrectToolForDrops()
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(WATERLOGGED)));
+ public static final Block TUBE_CORAL_WALL_FAN = register(new Block("tube_coral_wall_fan", builder().pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(WATERLOGGED)));
+ public static final Block BRAIN_CORAL_WALL_FAN = register(new Block("brain_coral_wall_fan", builder().pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(WATERLOGGED)));
+ public static final Block BUBBLE_CORAL_WALL_FAN = register(new Block("bubble_coral_wall_fan", builder().pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(WATERLOGGED)));
+ public static final Block FIRE_CORAL_WALL_FAN = register(new Block("fire_coral_wall_fan", builder().pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(WATERLOGGED)));
+ public static final Block HORN_CORAL_WALL_FAN = register(new Block("horn_coral_wall_fan", builder().pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(WATERLOGGED)));
+ public static final Block SEA_PICKLE = register(new Block("sea_pickle", builder().pushReaction(PistonBehavior.DESTROY)
+ .intState(PICKLES)
+ .booleanState(WATERLOGGED)));
+ public static final Block BLUE_ICE = register(new Block("blue_ice", builder().destroyTime(2.8f)));
+ public static final Block CONDUIT = register(new Block("conduit", builder().setBlockEntity(BlockEntityType.CONDUIT).destroyTime(3.0f)
+ .booleanState(WATERLOGGED)));
+ public static final Block BAMBOO_SAPLING = register(new Block("bamboo_sapling", builder().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.BAMBOO)));
+ public static final Block BAMBOO = register(new Block("bamboo", builder().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY)
+ .intState(AGE_1)
+ .enumState(BAMBOO_LEAVES)
+ .intState(STAGE)));
+ public static final Block POTTED_BAMBOO = register(new FlowerPotBlock("potted_bamboo", BAMBOO, builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block VOID_AIR = register(new Block("void_air", builder()));
+ public static final Block CAVE_AIR = register(new Block("cave_air", builder()));
+ public static final Block BUBBLE_COLUMN = register(new Block("bubble_column", builder().pushReaction(PistonBehavior.DESTROY)
+ .booleanState(DRAG)));
+ public static final Block POLISHED_GRANITE_STAIRS = register(new Block("polished_granite_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block SMOOTH_RED_SANDSTONE_STAIRS = register(new Block("smooth_red_sandstone_stairs", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block MOSSY_STONE_BRICK_STAIRS = register(new Block("mossy_stone_brick_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block POLISHED_DIORITE_STAIRS = register(new Block("polished_diorite_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block MOSSY_COBBLESTONE_STAIRS = register(new Block("mossy_cobblestone_stairs", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block END_STONE_BRICK_STAIRS = register(new Block("end_stone_brick_stairs", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block STONE_STAIRS = register(new Block("stone_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block SMOOTH_SANDSTONE_STAIRS = register(new Block("smooth_sandstone_stairs", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block SMOOTH_QUARTZ_STAIRS = register(new Block("smooth_quartz_stairs", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block GRANITE_STAIRS = register(new Block("granite_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block ANDESITE_STAIRS = register(new Block("andesite_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block RED_NETHER_BRICK_STAIRS = register(new Block("red_nether_brick_stairs", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block POLISHED_ANDESITE_STAIRS = register(new Block("polished_andesite_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block DIORITE_STAIRS = register(new Block("diorite_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block POLISHED_GRANITE_SLAB = register(new Block("polished_granite_slab", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block SMOOTH_RED_SANDSTONE_SLAB = register(new Block("smooth_red_sandstone_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block MOSSY_STONE_BRICK_SLAB = register(new Block("mossy_stone_brick_slab", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block POLISHED_DIORITE_SLAB = register(new Block("polished_diorite_slab", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block MOSSY_COBBLESTONE_SLAB = register(new Block("mossy_cobblestone_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block END_STONE_BRICK_SLAB = register(new Block("end_stone_brick_slab", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block SMOOTH_SANDSTONE_SLAB = register(new Block("smooth_sandstone_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block SMOOTH_QUARTZ_SLAB = register(new Block("smooth_quartz_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block GRANITE_SLAB = register(new Block("granite_slab", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block ANDESITE_SLAB = register(new Block("andesite_slab", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block RED_NETHER_BRICK_SLAB = register(new Block("red_nether_brick_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block POLISHED_ANDESITE_SLAB = register(new Block("polished_andesite_slab", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block DIORITE_SLAB = register(new Block("diorite_slab", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block BRICK_WALL = register(new Block("brick_wall", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .enumState(EAST_WALL)
+ .enumState(NORTH_WALL)
+ .enumState(SOUTH_WALL)
+ .booleanState(UP)
+ .booleanState(WATERLOGGED)
+ .enumState(WEST_WALL)));
+ public static final Block PRISMARINE_WALL = register(new Block("prismarine_wall", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(EAST_WALL)
+ .enumState(NORTH_WALL)
+ .enumState(SOUTH_WALL)
+ .booleanState(UP)
+ .booleanState(WATERLOGGED)
+ .enumState(WEST_WALL)));
+ public static final Block RED_SANDSTONE_WALL = register(new Block("red_sandstone_wall", builder().requiresCorrectToolForDrops().destroyTime(0.8f)
+ .enumState(EAST_WALL)
+ .enumState(NORTH_WALL)
+ .enumState(SOUTH_WALL)
+ .booleanState(UP)
+ .booleanState(WATERLOGGED)
+ .enumState(WEST_WALL)));
+ public static final Block MOSSY_STONE_BRICK_WALL = register(new Block("mossy_stone_brick_wall", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(EAST_WALL)
+ .enumState(NORTH_WALL)
+ .enumState(SOUTH_WALL)
+ .booleanState(UP)
+ .booleanState(WATERLOGGED)
+ .enumState(WEST_WALL)));
+ public static final Block GRANITE_WALL = register(new Block("granite_wall", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(EAST_WALL)
+ .enumState(NORTH_WALL)
+ .enumState(SOUTH_WALL)
+ .booleanState(UP)
+ .booleanState(WATERLOGGED)
+ .enumState(WEST_WALL)));
+ public static final Block STONE_BRICK_WALL = register(new Block("stone_brick_wall", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(EAST_WALL)
+ .enumState(NORTH_WALL)
+ .enumState(SOUTH_WALL)
+ .booleanState(UP)
+ .booleanState(WATERLOGGED)
+ .enumState(WEST_WALL)));
+ public static final Block MUD_BRICK_WALL = register(new Block("mud_brick_wall", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(EAST_WALL)
+ .enumState(NORTH_WALL)
+ .enumState(SOUTH_WALL)
+ .booleanState(UP)
+ .booleanState(WATERLOGGED)
+ .enumState(WEST_WALL)));
+ public static final Block NETHER_BRICK_WALL = register(new Block("nether_brick_wall", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .enumState(EAST_WALL)
+ .enumState(NORTH_WALL)
+ .enumState(SOUTH_WALL)
+ .booleanState(UP)
+ .booleanState(WATERLOGGED)
+ .enumState(WEST_WALL)));
+ public static final Block ANDESITE_WALL = register(new Block("andesite_wall", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(EAST_WALL)
+ .enumState(NORTH_WALL)
+ .enumState(SOUTH_WALL)
+ .booleanState(UP)
+ .booleanState(WATERLOGGED)
+ .enumState(WEST_WALL)));
+ public static final Block RED_NETHER_BRICK_WALL = register(new Block("red_nether_brick_wall", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .enumState(EAST_WALL)
+ .enumState(NORTH_WALL)
+ .enumState(SOUTH_WALL)
+ .booleanState(UP)
+ .booleanState(WATERLOGGED)
+ .enumState(WEST_WALL)));
+ public static final Block SANDSTONE_WALL = register(new Block("sandstone_wall", builder().requiresCorrectToolForDrops().destroyTime(0.8f)
+ .enumState(EAST_WALL)
+ .enumState(NORTH_WALL)
+ .enumState(SOUTH_WALL)
+ .booleanState(UP)
+ .booleanState(WATERLOGGED)
+ .enumState(WEST_WALL)));
+ public static final Block END_STONE_BRICK_WALL = register(new Block("end_stone_brick_wall", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .enumState(EAST_WALL)
+ .enumState(NORTH_WALL)
+ .enumState(SOUTH_WALL)
+ .booleanState(UP)
+ .booleanState(WATERLOGGED)
+ .enumState(WEST_WALL)));
+ public static final Block DIORITE_WALL = register(new Block("diorite_wall", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(EAST_WALL)
+ .enumState(NORTH_WALL)
+ .enumState(SOUTH_WALL)
+ .booleanState(UP)
+ .booleanState(WATERLOGGED)
+ .enumState(WEST_WALL)));
+ public static final Block SCAFFOLDING = register(new Block("scaffolding", builder().pushReaction(PistonBehavior.DESTROY)
+ .booleanState(BOTTOM)
+ .intState(STABILITY_DISTANCE)
+ .booleanState(WATERLOGGED)));
+ public static final Block LOOM = register(new Block("loom", builder().destroyTime(2.5f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block BARREL = register(new Block("barrel", builder().setBlockEntity(BlockEntityType.BARREL).destroyTime(2.5f)
+ .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN)
+ .booleanState(OPEN)));
+ public static final Block SMOKER = register(new Block("smoker", builder().setBlockEntity(BlockEntityType.SMOKER).requiresCorrectToolForDrops().destroyTime(3.5f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(LIT)));
+ public static final Block BLAST_FURNACE = register(new Block("blast_furnace", builder().setBlockEntity(BlockEntityType.BLAST_FURNACE).requiresCorrectToolForDrops().destroyTime(3.5f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(LIT)));
+ public static final Block CARTOGRAPHY_TABLE = register(new Block("cartography_table", builder().destroyTime(2.5f)));
+ public static final Block FLETCHING_TABLE = register(new Block("fletching_table", builder().destroyTime(2.5f)));
+ public static final Block GRINDSTONE = register(new Block("grindstone", builder().requiresCorrectToolForDrops().destroyTime(2.0f).pushReaction(PistonBehavior.BLOCK)
+ .enumState(ATTACH_FACE)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block LECTERN = register(new LecternBlock("lectern", builder().setBlockEntity(BlockEntityType.LECTERN).destroyTime(2.5f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(HAS_BOOK)
+ .booleanState(POWERED)));
+ public static final Block SMITHING_TABLE = register(new Block("smithing_table", builder().destroyTime(2.5f)));
+ public static final Block STONECUTTER = register(new Block("stonecutter", builder().requiresCorrectToolForDrops().destroyTime(3.5f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block BELL = register(new Block("bell", builder().setBlockEntity(BlockEntityType.BELL).requiresCorrectToolForDrops().destroyTime(5.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(BELL_ATTACHMENT)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(POWERED)));
+ public static final Block LANTERN = register(new Block("lantern", builder().requiresCorrectToolForDrops().destroyTime(3.5f).pushReaction(PistonBehavior.DESTROY)
+ .booleanState(HANGING)
+ .booleanState(WATERLOGGED)));
+ public static final Block SOUL_LANTERN = register(new Block("soul_lantern", builder().requiresCorrectToolForDrops().destroyTime(3.5f).pushReaction(PistonBehavior.DESTROY)
+ .booleanState(HANGING)
+ .booleanState(WATERLOGGED)));
+ public static final Block CAMPFIRE = register(new Block("campfire", builder().setBlockEntity(BlockEntityType.CAMPFIRE).destroyTime(2.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(LIT)
+ .booleanState(SIGNAL_FIRE)
+ .booleanState(WATERLOGGED)));
+ public static final Block SOUL_CAMPFIRE = register(new Block("soul_campfire", builder().setBlockEntity(BlockEntityType.CAMPFIRE).destroyTime(2.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(LIT)
+ .booleanState(SIGNAL_FIRE)
+ .booleanState(WATERLOGGED)));
+ public static final Block SWEET_BERRY_BUSH = register(new Block("sweet_berry_bush", builder().pushReaction(PistonBehavior.DESTROY)
+ .intState(AGE_3)));
+ public static final Block WARPED_STEM = register(new Block("warped_stem", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block STRIPPED_WARPED_STEM = register(new Block("stripped_warped_stem", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block WARPED_HYPHAE = register(new Block("warped_hyphae", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block STRIPPED_WARPED_HYPHAE = register(new Block("stripped_warped_hyphae", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block WARPED_NYLIUM = register(new Block("warped_nylium", builder().requiresCorrectToolForDrops().destroyTime(0.4f)));
+ public static final Block WARPED_FUNGUS = register(new Block("warped_fungus", builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block WARPED_WART_BLOCK = register(new Block("warped_wart_block", builder().destroyTime(1.0f)));
+ public static final Block WARPED_ROOTS = register(new Block("warped_roots", builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block NETHER_SPROUTS = register(new Block("nether_sprouts", builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block CRIMSON_STEM = register(new Block("crimson_stem", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block STRIPPED_CRIMSON_STEM = register(new Block("stripped_crimson_stem", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block CRIMSON_HYPHAE = register(new Block("crimson_hyphae", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block STRIPPED_CRIMSON_HYPHAE = register(new Block("stripped_crimson_hyphae", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block CRIMSON_NYLIUM = register(new Block("crimson_nylium", builder().requiresCorrectToolForDrops().destroyTime(0.4f)));
+ public static final Block CRIMSON_FUNGUS = register(new Block("crimson_fungus", builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block SHROOMLIGHT = register(new Block("shroomlight", builder().destroyTime(1.0f)));
+ public static final Block WEEPING_VINES = register(new Block("weeping_vines", builder().pushReaction(PistonBehavior.DESTROY)
+ .intState(AGE_25)));
+ public static final Block WEEPING_VINES_PLANT = register(new Block("weeping_vines_plant", builder().pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.WEEPING_VINES)));
+ public static final Block TWISTING_VINES = register(new Block("twisting_vines", builder().pushReaction(PistonBehavior.DESTROY)
+ .intState(AGE_25)));
+ public static final Block TWISTING_VINES_PLANT = register(new Block("twisting_vines_plant", builder().pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.TWISTING_VINES)));
+ public static final Block CRIMSON_ROOTS = register(new Block("crimson_roots", builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block CRIMSON_PLANKS = register(new Block("crimson_planks", builder().destroyTime(2.0f)));
+ public static final Block WARPED_PLANKS = register(new Block("warped_planks", builder().destroyTime(2.0f)));
+ public static final Block CRIMSON_SLAB = register(new Block("crimson_slab", builder().destroyTime(2.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block WARPED_SLAB = register(new Block("warped_slab", builder().destroyTime(2.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block CRIMSON_PRESSURE_PLATE = register(new Block("crimson_pressure_plate", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY)
+ .booleanState(POWERED)));
+ public static final Block WARPED_PRESSURE_PLATE = register(new Block("warped_pressure_plate", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY)
+ .booleanState(POWERED)));
+ public static final Block CRIMSON_FENCE = register(new Block("crimson_fence", builder().destroyTime(2.0f)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(SOUTH)
+ .booleanState(WATERLOGGED)
+ .booleanState(WEST)));
+ public static final Block WARPED_FENCE = register(new Block("warped_fence", builder().destroyTime(2.0f)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(SOUTH)
+ .booleanState(WATERLOGGED)
+ .booleanState(WEST)));
+ public static final Block CRIMSON_TRAPDOOR = register(new TrapDoorBlock("crimson_trapdoor", builder().destroyTime(3.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .booleanState(OPEN)
+ .booleanState(POWERED)
+ .booleanState(WATERLOGGED)));
+ public static final Block WARPED_TRAPDOOR = register(new TrapDoorBlock("warped_trapdoor", builder().destroyTime(3.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .booleanState(OPEN)
+ .booleanState(POWERED)
+ .booleanState(WATERLOGGED)));
+ public static final Block CRIMSON_FENCE_GATE = register(new Block("crimson_fence_gate", builder().destroyTime(2.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(IN_WALL)
+ .booleanState(OPEN)
+ .booleanState(POWERED)));
+ public static final Block WARPED_FENCE_GATE = register(new Block("warped_fence_gate", builder().destroyTime(2.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(IN_WALL)
+ .booleanState(OPEN)
+ .booleanState(POWERED)));
+ public static final Block CRIMSON_STAIRS = register(new Block("crimson_stairs", builder().destroyTime(2.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block WARPED_STAIRS = register(new Block("warped_stairs", builder().destroyTime(2.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block CRIMSON_BUTTON = register(new Block("crimson_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(ATTACH_FACE)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(POWERED)));
+ public static final Block WARPED_BUTTON = register(new Block("warped_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(ATTACH_FACE)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(POWERED)));
+ public static final Block CRIMSON_DOOR = register(new DoorBlock("crimson_door", builder().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(DOUBLE_BLOCK_HALF)
+ .enumState(DOOR_HINGE)
+ .booleanState(OPEN)
+ .booleanState(POWERED)));
+ public static final Block WARPED_DOOR = register(new DoorBlock("warped_door", builder().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(DOUBLE_BLOCK_HALF)
+ .enumState(DOOR_HINGE)
+ .booleanState(OPEN)
+ .booleanState(POWERED)));
+ public static final Block CRIMSON_SIGN = register(new Block("crimson_sign", builder().setBlockEntity(BlockEntityType.SIGN).destroyTime(1.0f)
+ .intState(ROTATION_16)
+ .booleanState(WATERLOGGED)));
+ public static final Block WARPED_SIGN = register(new Block("warped_sign", builder().setBlockEntity(BlockEntityType.SIGN).destroyTime(1.0f)
+ .intState(ROTATION_16)
+ .booleanState(WATERLOGGED)));
+ public static final Block CRIMSON_WALL_SIGN = register(new Block("crimson_wall_sign", builder().setBlockEntity(BlockEntityType.SIGN).destroyTime(1.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(WATERLOGGED)));
+ public static final Block WARPED_WALL_SIGN = register(new Block("warped_wall_sign", builder().setBlockEntity(BlockEntityType.SIGN).destroyTime(1.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(WATERLOGGED)));
+ public static final Block STRUCTURE_BLOCK = register(new Block("structure_block", builder().setBlockEntity(BlockEntityType.STRUCTURE_BLOCK).requiresCorrectToolForDrops().destroyTime(-1.0f)
+ .enumState(STRUCTUREBLOCK_MODE)));
+ public static final Block JIGSAW = register(new Block("jigsaw", builder().setBlockEntity(BlockEntityType.JIGSAW).requiresCorrectToolForDrops().destroyTime(-1.0f)
+ .enumState(ORIENTATION, FrontAndTop.VALUES)));
+ public static final Block COMPOSTER = register(new Block("composter", builder().destroyTime(0.6f)
+ .intState(LEVEL_COMPOSTER)));
+ public static final Block TARGET = register(new Block("target", builder().destroyTime(0.5f)
+ .intState(POWER)));
+ public static final Block BEE_NEST = register(new Block("bee_nest", builder().setBlockEntity(BlockEntityType.BEEHIVE).destroyTime(0.3f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .intState(LEVEL_HONEY)));
+ public static final Block BEEHIVE = register(new Block("beehive", builder().setBlockEntity(BlockEntityType.BEEHIVE).destroyTime(0.6f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .intState(LEVEL_HONEY)));
+ public static final Block HONEY_BLOCK = register(new HoneyBlock("honey_block", builder()));
+ public static final Block HONEYCOMB_BLOCK = register(new Block("honeycomb_block", builder().destroyTime(0.6f)));
+ public static final Block NETHERITE_BLOCK = register(new Block("netherite_block", builder().requiresCorrectToolForDrops().destroyTime(50.0f)));
+ public static final Block ANCIENT_DEBRIS = register(new Block("ancient_debris", builder().requiresCorrectToolForDrops().destroyTime(30.0f)));
+ public static final Block CRYING_OBSIDIAN = register(new Block("crying_obsidian", builder().requiresCorrectToolForDrops().destroyTime(50.0f)));
+ public static final Block RESPAWN_ANCHOR = register(new Block("respawn_anchor", builder().requiresCorrectToolForDrops().destroyTime(50.0f)
+ .intState(RESPAWN_ANCHOR_CHARGES)));
+ public static final Block POTTED_CRIMSON_FUNGUS = register(new FlowerPotBlock("potted_crimson_fungus", CRIMSON_FUNGUS, builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block POTTED_WARPED_FUNGUS = register(new FlowerPotBlock("potted_warped_fungus", WARPED_FUNGUS, builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block POTTED_CRIMSON_ROOTS = register(new FlowerPotBlock("potted_crimson_roots", CRIMSON_ROOTS, builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block POTTED_WARPED_ROOTS = register(new FlowerPotBlock("potted_warped_roots", WARPED_ROOTS, builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block LODESTONE = register(new Block("lodestone", builder().requiresCorrectToolForDrops().destroyTime(3.5f).pushReaction(PistonBehavior.BLOCK)));
+ public static final Block BLACKSTONE = register(new Block("blackstone", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
+ public static final Block BLACKSTONE_STAIRS = register(new Block("blackstone_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block BLACKSTONE_WALL = register(new Block("blackstone_wall", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(EAST_WALL)
+ .enumState(NORTH_WALL)
+ .enumState(SOUTH_WALL)
+ .booleanState(UP)
+ .booleanState(WATERLOGGED)
+ .enumState(WEST_WALL)));
+ public static final Block BLACKSTONE_SLAB = register(new Block("blackstone_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block POLISHED_BLACKSTONE = register(new Block("polished_blackstone", builder().requiresCorrectToolForDrops().destroyTime(2.0f)));
+ public static final Block POLISHED_BLACKSTONE_BRICKS = register(new Block("polished_blackstone_bricks", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
+ public static final Block CRACKED_POLISHED_BLACKSTONE_BRICKS = register(new Block("cracked_polished_blackstone_bricks", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
+ public static final Block CHISELED_POLISHED_BLACKSTONE = register(new Block("chiseled_polished_blackstone", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
+ public static final Block POLISHED_BLACKSTONE_BRICK_SLAB = register(new Block("polished_blackstone_brick_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block POLISHED_BLACKSTONE_BRICK_STAIRS = register(new Block("polished_blackstone_brick_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block POLISHED_BLACKSTONE_BRICK_WALL = register(new Block("polished_blackstone_brick_wall", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(EAST_WALL)
+ .enumState(NORTH_WALL)
+ .enumState(SOUTH_WALL)
+ .booleanState(UP)
+ .booleanState(WATERLOGGED)
+ .enumState(WEST_WALL)));
+ public static final Block GILDED_BLACKSTONE = register(new Block("gilded_blackstone", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
+ public static final Block POLISHED_BLACKSTONE_STAIRS = register(new Block("polished_blackstone_stairs", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block POLISHED_BLACKSTONE_SLAB = register(new Block("polished_blackstone_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block POLISHED_BLACKSTONE_PRESSURE_PLATE = register(new Block("polished_blackstone_pressure_plate", builder().requiresCorrectToolForDrops().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY)
+ .booleanState(POWERED)));
+ public static final Block POLISHED_BLACKSTONE_BUTTON = register(new Block("polished_blackstone_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(ATTACH_FACE)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(POWERED)));
+ public static final Block POLISHED_BLACKSTONE_WALL = register(new Block("polished_blackstone_wall", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .enumState(EAST_WALL)
+ .enumState(NORTH_WALL)
+ .enumState(SOUTH_WALL)
+ .booleanState(UP)
+ .booleanState(WATERLOGGED)
+ .enumState(WEST_WALL)));
+ public static final Block CHISELED_NETHER_BRICKS = register(new Block("chiseled_nether_bricks", builder().requiresCorrectToolForDrops().destroyTime(2.0f)));
+ public static final Block CRACKED_NETHER_BRICKS = register(new Block("cracked_nether_bricks", builder().requiresCorrectToolForDrops().destroyTime(2.0f)));
+ public static final Block QUARTZ_BRICKS = register(new Block("quartz_bricks", builder().requiresCorrectToolForDrops().destroyTime(0.8f)));
+ public static final Block CANDLE = register(new Block("candle", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY)
+ .intState(CANDLES)
+ .booleanState(LIT)
+ .booleanState(WATERLOGGED)));
+ public static final Block WHITE_CANDLE = register(new Block("white_candle", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY)
+ .intState(CANDLES)
+ .booleanState(LIT)
+ .booleanState(WATERLOGGED)));
+ public static final Block ORANGE_CANDLE = register(new Block("orange_candle", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY)
+ .intState(CANDLES)
+ .booleanState(LIT)
+ .booleanState(WATERLOGGED)));
+ public static final Block MAGENTA_CANDLE = register(new Block("magenta_candle", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY)
+ .intState(CANDLES)
+ .booleanState(LIT)
+ .booleanState(WATERLOGGED)));
+ public static final Block LIGHT_BLUE_CANDLE = register(new Block("light_blue_candle", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY)
+ .intState(CANDLES)
+ .booleanState(LIT)
+ .booleanState(WATERLOGGED)));
+ public static final Block YELLOW_CANDLE = register(new Block("yellow_candle", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY)
+ .intState(CANDLES)
+ .booleanState(LIT)
+ .booleanState(WATERLOGGED)));
+ public static final Block LIME_CANDLE = register(new Block("lime_candle", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY)
+ .intState(CANDLES)
+ .booleanState(LIT)
+ .booleanState(WATERLOGGED)));
+ public static final Block PINK_CANDLE = register(new Block("pink_candle", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY)
+ .intState(CANDLES)
+ .booleanState(LIT)
+ .booleanState(WATERLOGGED)));
+ public static final Block GRAY_CANDLE = register(new Block("gray_candle", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY)
+ .intState(CANDLES)
+ .booleanState(LIT)
+ .booleanState(WATERLOGGED)));
+ public static final Block LIGHT_GRAY_CANDLE = register(new Block("light_gray_candle", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY)
+ .intState(CANDLES)
+ .booleanState(LIT)
+ .booleanState(WATERLOGGED)));
+ public static final Block CYAN_CANDLE = register(new Block("cyan_candle", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY)
+ .intState(CANDLES)
+ .booleanState(LIT)
+ .booleanState(WATERLOGGED)));
+ public static final Block PURPLE_CANDLE = register(new Block("purple_candle", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY)
+ .intState(CANDLES)
+ .booleanState(LIT)
+ .booleanState(WATERLOGGED)));
+ public static final Block BLUE_CANDLE = register(new Block("blue_candle", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY)
+ .intState(CANDLES)
+ .booleanState(LIT)
+ .booleanState(WATERLOGGED)));
+ public static final Block BROWN_CANDLE = register(new Block("brown_candle", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY)
+ .intState(CANDLES)
+ .booleanState(LIT)
+ .booleanState(WATERLOGGED)));
+ public static final Block GREEN_CANDLE = register(new Block("green_candle", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY)
+ .intState(CANDLES)
+ .booleanState(LIT)
+ .booleanState(WATERLOGGED)));
+ public static final Block RED_CANDLE = register(new Block("red_candle", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY)
+ .intState(CANDLES)
+ .booleanState(LIT)
+ .booleanState(WATERLOGGED)));
+ public static final Block BLACK_CANDLE = register(new Block("black_candle", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY)
+ .intState(CANDLES)
+ .booleanState(LIT)
+ .booleanState(WATERLOGGED)));
+ public static final Block CANDLE_CAKE = register(new Block("candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.CAKE)
+ .booleanState(LIT)));
+ public static final Block WHITE_CANDLE_CAKE = register(new Block("white_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.CAKE)
+ .booleanState(LIT)));
+ public static final Block ORANGE_CANDLE_CAKE = register(new Block("orange_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.CAKE)
+ .booleanState(LIT)));
+ public static final Block MAGENTA_CANDLE_CAKE = register(new Block("magenta_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.CAKE)
+ .booleanState(LIT)));
+ public static final Block LIGHT_BLUE_CANDLE_CAKE = register(new Block("light_blue_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.CAKE)
+ .booleanState(LIT)));
+ public static final Block YELLOW_CANDLE_CAKE = register(new Block("yellow_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.CAKE)
+ .booleanState(LIT)));
+ public static final Block LIME_CANDLE_CAKE = register(new Block("lime_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.CAKE)
+ .booleanState(LIT)));
+ public static final Block PINK_CANDLE_CAKE = register(new Block("pink_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.CAKE)
+ .booleanState(LIT)));
+ public static final Block GRAY_CANDLE_CAKE = register(new Block("gray_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.CAKE)
+ .booleanState(LIT)));
+ public static final Block LIGHT_GRAY_CANDLE_CAKE = register(new Block("light_gray_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.CAKE)
+ .booleanState(LIT)));
+ public static final Block CYAN_CANDLE_CAKE = register(new Block("cyan_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.CAKE)
+ .booleanState(LIT)));
+ public static final Block PURPLE_CANDLE_CAKE = register(new Block("purple_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.CAKE)
+ .booleanState(LIT)));
+ public static final Block BLUE_CANDLE_CAKE = register(new Block("blue_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.CAKE)
+ .booleanState(LIT)));
+ public static final Block BROWN_CANDLE_CAKE = register(new Block("brown_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.CAKE)
+ .booleanState(LIT)));
+ public static final Block GREEN_CANDLE_CAKE = register(new Block("green_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.CAKE)
+ .booleanState(LIT)));
+ public static final Block RED_CANDLE_CAKE = register(new Block("red_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.CAKE)
+ .booleanState(LIT)));
+ public static final Block BLACK_CANDLE_CAKE = register(new Block("black_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.CAKE)
+ .booleanState(LIT)));
+ public static final Block AMETHYST_BLOCK = register(new Block("amethyst_block", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
+ public static final Block BUDDING_AMETHYST = register(new Block("budding_amethyst", builder().requiresCorrectToolForDrops().destroyTime(1.5f).pushReaction(PistonBehavior.DESTROY)));
+ public static final Block AMETHYST_CLUSTER = register(new Block("amethyst_cluster", builder().destroyTime(1.5f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN)
+ .booleanState(WATERLOGGED)));
+ public static final Block LARGE_AMETHYST_BUD = register(new Block("large_amethyst_bud", builder().destroyTime(1.5f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN)
+ .booleanState(WATERLOGGED)));
+ public static final Block MEDIUM_AMETHYST_BUD = register(new Block("medium_amethyst_bud", builder().destroyTime(1.5f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN)
+ .booleanState(WATERLOGGED)));
+ public static final Block SMALL_AMETHYST_BUD = register(new Block("small_amethyst_bud", builder().destroyTime(1.5f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN)
+ .booleanState(WATERLOGGED)));
+ public static final Block TUFF = register(new Block("tuff", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
+ public static final Block TUFF_SLAB = register(new Block("tuff_slab", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block TUFF_STAIRS = register(new Block("tuff_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block TUFF_WALL = register(new Block("tuff_wall", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(EAST_WALL)
+ .enumState(NORTH_WALL)
+ .enumState(SOUTH_WALL)
+ .booleanState(UP)
+ .booleanState(WATERLOGGED)
+ .enumState(WEST_WALL)));
+ public static final Block POLISHED_TUFF = register(new Block("polished_tuff", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
+ public static final Block POLISHED_TUFF_SLAB = register(new Block("polished_tuff_slab", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block POLISHED_TUFF_STAIRS = register(new Block("polished_tuff_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block POLISHED_TUFF_WALL = register(new Block("polished_tuff_wall", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(EAST_WALL)
+ .enumState(NORTH_WALL)
+ .enumState(SOUTH_WALL)
+ .booleanState(UP)
+ .booleanState(WATERLOGGED)
+ .enumState(WEST_WALL)));
+ public static final Block CHISELED_TUFF = register(new Block("chiseled_tuff", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
+ public static final Block TUFF_BRICKS = register(new Block("tuff_bricks", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
+ public static final Block TUFF_BRICK_SLAB = register(new Block("tuff_brick_slab", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block TUFF_BRICK_STAIRS = register(new Block("tuff_brick_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block TUFF_BRICK_WALL = register(new Block("tuff_brick_wall", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(EAST_WALL)
+ .enumState(NORTH_WALL)
+ .enumState(SOUTH_WALL)
+ .booleanState(UP)
+ .booleanState(WATERLOGGED)
+ .enumState(WEST_WALL)));
+ public static final Block CHISELED_TUFF_BRICKS = register(new Block("chiseled_tuff_bricks", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
+ public static final Block CALCITE = register(new Block("calcite", builder().requiresCorrectToolForDrops().destroyTime(0.75f)));
+ public static final Block TINTED_GLASS = register(new Block("tinted_glass", builder().destroyTime(0.3f)));
+ public static final Block POWDER_SNOW = register(new Block("powder_snow", builder().destroyTime(0.25f)));
+ public static final Block SCULK_SENSOR = register(new Block("sculk_sensor", builder().setBlockEntity(BlockEntityType.SCULK_SENSOR).destroyTime(1.5f)
+ .intState(POWER)
+ .enumState(SCULK_SENSOR_PHASE)
+ .booleanState(WATERLOGGED)));
+ public static final Block CALIBRATED_SCULK_SENSOR = register(new Block("calibrated_sculk_sensor", builder().setBlockEntity(BlockEntityType.CALIBRATED_SCULK_SENSOR).destroyTime(1.5f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .intState(POWER)
+ .enumState(SCULK_SENSOR_PHASE)
+ .booleanState(WATERLOGGED)));
+ public static final Block SCULK = register(new Block("sculk", builder().destroyTime(0.2f)));
+ public static final Block SCULK_VEIN = register(new Block("sculk_vein", builder().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY)
+ .booleanState(DOWN)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(SOUTH)
+ .booleanState(UP)
+ .booleanState(WATERLOGGED)
+ .booleanState(WEST)));
+ public static final Block SCULK_CATALYST = register(new Block("sculk_catalyst", builder().setBlockEntity(BlockEntityType.SCULK_CATALYST).destroyTime(3.0f)
+ .booleanState(BLOOM)));
+ public static final Block SCULK_SHRIEKER = register(new Block("sculk_shrieker", builder().setBlockEntity(BlockEntityType.SCULK_SHRIEKER).destroyTime(3.0f)
+ .booleanState(CAN_SUMMON)
+ .booleanState(SHRIEKING)
+ .booleanState(WATERLOGGED)));
+ public static final Block COPPER_BLOCK = register(new Block("copper_block", builder().requiresCorrectToolForDrops().destroyTime(3.0f)));
+ public static final Block EXPOSED_COPPER = register(new Block("exposed_copper", builder().requiresCorrectToolForDrops().destroyTime(3.0f)));
+ public static final Block WEATHERED_COPPER = register(new Block("weathered_copper", builder().requiresCorrectToolForDrops().destroyTime(3.0f)));
+ public static final Block OXIDIZED_COPPER = register(new Block("oxidized_copper", builder().requiresCorrectToolForDrops().destroyTime(3.0f)));
+ public static final Block COPPER_ORE = register(new Block("copper_ore", builder().requiresCorrectToolForDrops().destroyTime(3.0f)));
+ public static final Block DEEPSLATE_COPPER_ORE = register(new Block("deepslate_copper_ore", builder().requiresCorrectToolForDrops().destroyTime(4.5f)));
+ public static final Block OXIDIZED_CUT_COPPER = register(new Block("oxidized_cut_copper", builder().requiresCorrectToolForDrops().destroyTime(3.0f)));
+ public static final Block WEATHERED_CUT_COPPER = register(new Block("weathered_cut_copper", builder().requiresCorrectToolForDrops().destroyTime(3.0f)));
+ public static final Block EXPOSED_CUT_COPPER = register(new Block("exposed_cut_copper", builder().requiresCorrectToolForDrops().destroyTime(3.0f)));
+ public static final Block CUT_COPPER = register(new Block("cut_copper", builder().requiresCorrectToolForDrops().destroyTime(3.0f)));
+ public static final Block OXIDIZED_CHISELED_COPPER = register(new Block("oxidized_chiseled_copper", builder().requiresCorrectToolForDrops().destroyTime(3.0f)));
+ public static final Block WEATHERED_CHISELED_COPPER = register(new Block("weathered_chiseled_copper", builder().requiresCorrectToolForDrops().destroyTime(3.0f)));
+ public static final Block EXPOSED_CHISELED_COPPER = register(new Block("exposed_chiseled_copper", builder().requiresCorrectToolForDrops().destroyTime(3.0f)));
+ public static final Block CHISELED_COPPER = register(new Block("chiseled_copper", builder().requiresCorrectToolForDrops().destroyTime(3.0f)));
+ public static final Block WAXED_OXIDIZED_CHISELED_COPPER = register(new Block("waxed_oxidized_chiseled_copper", builder().requiresCorrectToolForDrops().destroyTime(3.0f)));
+ public static final Block WAXED_WEATHERED_CHISELED_COPPER = register(new Block("waxed_weathered_chiseled_copper", builder().requiresCorrectToolForDrops().destroyTime(3.0f)));
+ public static final Block WAXED_EXPOSED_CHISELED_COPPER = register(new Block("waxed_exposed_chiseled_copper", builder().requiresCorrectToolForDrops().destroyTime(3.0f)));
+ public static final Block WAXED_CHISELED_COPPER = register(new Block("waxed_chiseled_copper", builder().requiresCorrectToolForDrops().destroyTime(3.0f)));
+ public static final Block OXIDIZED_CUT_COPPER_STAIRS = register(new Block("oxidized_cut_copper_stairs", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block WEATHERED_CUT_COPPER_STAIRS = register(new Block("weathered_cut_copper_stairs", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block EXPOSED_CUT_COPPER_STAIRS = register(new Block("exposed_cut_copper_stairs", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block CUT_COPPER_STAIRS = register(new Block("cut_copper_stairs", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block OXIDIZED_CUT_COPPER_SLAB = register(new Block("oxidized_cut_copper_slab", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block WEATHERED_CUT_COPPER_SLAB = register(new Block("weathered_cut_copper_slab", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block EXPOSED_CUT_COPPER_SLAB = register(new Block("exposed_cut_copper_slab", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block CUT_COPPER_SLAB = register(new Block("cut_copper_slab", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block WAXED_COPPER_BLOCK = register(new Block("waxed_copper_block", builder().requiresCorrectToolForDrops().destroyTime(3.0f)));
+ public static final Block WAXED_WEATHERED_COPPER = register(new Block("waxed_weathered_copper", builder().requiresCorrectToolForDrops().destroyTime(3.0f)));
+ public static final Block WAXED_EXPOSED_COPPER = register(new Block("waxed_exposed_copper", builder().requiresCorrectToolForDrops().destroyTime(3.0f)));
+ public static final Block WAXED_OXIDIZED_COPPER = register(new Block("waxed_oxidized_copper", builder().requiresCorrectToolForDrops().destroyTime(3.0f)));
+ public static final Block WAXED_OXIDIZED_CUT_COPPER = register(new Block("waxed_oxidized_cut_copper", builder().requiresCorrectToolForDrops().destroyTime(3.0f)));
+ public static final Block WAXED_WEATHERED_CUT_COPPER = register(new Block("waxed_weathered_cut_copper", builder().requiresCorrectToolForDrops().destroyTime(3.0f)));
+ public static final Block WAXED_EXPOSED_CUT_COPPER = register(new Block("waxed_exposed_cut_copper", builder().requiresCorrectToolForDrops().destroyTime(3.0f)));
+ public static final Block WAXED_CUT_COPPER = register(new Block("waxed_cut_copper", builder().requiresCorrectToolForDrops().destroyTime(3.0f)));
+ public static final Block WAXED_OXIDIZED_CUT_COPPER_STAIRS = register(new Block("waxed_oxidized_cut_copper_stairs", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block WAXED_WEATHERED_CUT_COPPER_STAIRS = register(new Block("waxed_weathered_cut_copper_stairs", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block WAXED_EXPOSED_CUT_COPPER_STAIRS = register(new Block("waxed_exposed_cut_copper_stairs", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block WAXED_CUT_COPPER_STAIRS = register(new Block("waxed_cut_copper_stairs", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block WAXED_OXIDIZED_CUT_COPPER_SLAB = register(new Block("waxed_oxidized_cut_copper_slab", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block WAXED_WEATHERED_CUT_COPPER_SLAB = register(new Block("waxed_weathered_cut_copper_slab", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block WAXED_EXPOSED_CUT_COPPER_SLAB = register(new Block("waxed_exposed_cut_copper_slab", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block WAXED_CUT_COPPER_SLAB = register(new Block("waxed_cut_copper_slab", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block COPPER_DOOR = register(new DoorBlock("copper_door", builder().requiresCorrectToolForDrops().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(DOUBLE_BLOCK_HALF)
+ .enumState(DOOR_HINGE)
+ .booleanState(OPEN)
+ .booleanState(POWERED)));
+ public static final Block EXPOSED_COPPER_DOOR = register(new DoorBlock("exposed_copper_door", builder().requiresCorrectToolForDrops().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(DOUBLE_BLOCK_HALF)
+ .enumState(DOOR_HINGE)
+ .booleanState(OPEN)
+ .booleanState(POWERED)));
+ public static final Block OXIDIZED_COPPER_DOOR = register(new DoorBlock("oxidized_copper_door", builder().requiresCorrectToolForDrops().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(DOUBLE_BLOCK_HALF)
+ .enumState(DOOR_HINGE)
+ .booleanState(OPEN)
+ .booleanState(POWERED)));
+ public static final Block WEATHERED_COPPER_DOOR = register(new DoorBlock("weathered_copper_door", builder().requiresCorrectToolForDrops().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(DOUBLE_BLOCK_HALF)
+ .enumState(DOOR_HINGE)
+ .booleanState(OPEN)
+ .booleanState(POWERED)));
+ public static final Block WAXED_COPPER_DOOR = register(new DoorBlock("waxed_copper_door", builder().requiresCorrectToolForDrops().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(DOUBLE_BLOCK_HALF)
+ .enumState(DOOR_HINGE)
+ .booleanState(OPEN)
+ .booleanState(POWERED)));
+ public static final Block WAXED_EXPOSED_COPPER_DOOR = register(new DoorBlock("waxed_exposed_copper_door", builder().requiresCorrectToolForDrops().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(DOUBLE_BLOCK_HALF)
+ .enumState(DOOR_HINGE)
+ .booleanState(OPEN)
+ .booleanState(POWERED)));
+ public static final Block WAXED_OXIDIZED_COPPER_DOOR = register(new DoorBlock("waxed_oxidized_copper_door", builder().requiresCorrectToolForDrops().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(DOUBLE_BLOCK_HALF)
+ .enumState(DOOR_HINGE)
+ .booleanState(OPEN)
+ .booleanState(POWERED)));
+ public static final Block WAXED_WEATHERED_COPPER_DOOR = register(new DoorBlock("waxed_weathered_copper_door", builder().requiresCorrectToolForDrops().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(DOUBLE_BLOCK_HALF)
+ .enumState(DOOR_HINGE)
+ .booleanState(OPEN)
+ .booleanState(POWERED)));
+ public static final Block COPPER_TRAPDOOR = register(new TrapDoorBlock("copper_trapdoor", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .booleanState(OPEN)
+ .booleanState(POWERED)
+ .booleanState(WATERLOGGED)));
+ public static final Block EXPOSED_COPPER_TRAPDOOR = register(new TrapDoorBlock("exposed_copper_trapdoor", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .booleanState(OPEN)
+ .booleanState(POWERED)
+ .booleanState(WATERLOGGED)));
+ public static final Block OXIDIZED_COPPER_TRAPDOOR = register(new TrapDoorBlock("oxidized_copper_trapdoor", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .booleanState(OPEN)
+ .booleanState(POWERED)
+ .booleanState(WATERLOGGED)));
+ public static final Block WEATHERED_COPPER_TRAPDOOR = register(new TrapDoorBlock("weathered_copper_trapdoor", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .booleanState(OPEN)
+ .booleanState(POWERED)
+ .booleanState(WATERLOGGED)));
+ public static final Block WAXED_COPPER_TRAPDOOR = register(new TrapDoorBlock("waxed_copper_trapdoor", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .booleanState(OPEN)
+ .booleanState(POWERED)
+ .booleanState(WATERLOGGED)));
+ public static final Block WAXED_EXPOSED_COPPER_TRAPDOOR = register(new TrapDoorBlock("waxed_exposed_copper_trapdoor", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .booleanState(OPEN)
+ .booleanState(POWERED)
+ .booleanState(WATERLOGGED)));
+ public static final Block WAXED_OXIDIZED_COPPER_TRAPDOOR = register(new TrapDoorBlock("waxed_oxidized_copper_trapdoor", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .booleanState(OPEN)
+ .booleanState(POWERED)
+ .booleanState(WATERLOGGED)));
+ public static final Block WAXED_WEATHERED_COPPER_TRAPDOOR = register(new TrapDoorBlock("waxed_weathered_copper_trapdoor", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .booleanState(OPEN)
+ .booleanState(POWERED)
+ .booleanState(WATERLOGGED)));
+ public static final Block COPPER_GRATE = register(new Block("copper_grate", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .booleanState(WATERLOGGED)));
+ public static final Block EXPOSED_COPPER_GRATE = register(new Block("exposed_copper_grate", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .booleanState(WATERLOGGED)));
+ public static final Block WEATHERED_COPPER_GRATE = register(new Block("weathered_copper_grate", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .booleanState(WATERLOGGED)));
+ public static final Block OXIDIZED_COPPER_GRATE = register(new Block("oxidized_copper_grate", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .booleanState(WATERLOGGED)));
+ public static final Block WAXED_COPPER_GRATE = register(new Block("waxed_copper_grate", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .booleanState(WATERLOGGED)));
+ public static final Block WAXED_EXPOSED_COPPER_GRATE = register(new Block("waxed_exposed_copper_grate", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .booleanState(WATERLOGGED)));
+ public static final Block WAXED_WEATHERED_COPPER_GRATE = register(new Block("waxed_weathered_copper_grate", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .booleanState(WATERLOGGED)));
+ public static final Block WAXED_OXIDIZED_COPPER_GRATE = register(new Block("waxed_oxidized_copper_grate", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .booleanState(WATERLOGGED)));
+ public static final Block COPPER_BULB = register(new Block("copper_bulb", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .booleanState(LIT)
+ .booleanState(POWERED)));
+ public static final Block EXPOSED_COPPER_BULB = register(new Block("exposed_copper_bulb", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .booleanState(LIT)
+ .booleanState(POWERED)));
+ public static final Block WEATHERED_COPPER_BULB = register(new Block("weathered_copper_bulb", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .booleanState(LIT)
+ .booleanState(POWERED)));
+ public static final Block OXIDIZED_COPPER_BULB = register(new Block("oxidized_copper_bulb", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .booleanState(LIT)
+ .booleanState(POWERED)));
+ public static final Block WAXED_COPPER_BULB = register(new Block("waxed_copper_bulb", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .booleanState(LIT)
+ .booleanState(POWERED)));
+ public static final Block WAXED_EXPOSED_COPPER_BULB = register(new Block("waxed_exposed_copper_bulb", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .booleanState(LIT)
+ .booleanState(POWERED)));
+ public static final Block WAXED_WEATHERED_COPPER_BULB = register(new Block("waxed_weathered_copper_bulb", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .booleanState(LIT)
+ .booleanState(POWERED)));
+ public static final Block WAXED_OXIDIZED_COPPER_BULB = register(new Block("waxed_oxidized_copper_bulb", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .booleanState(LIT)
+ .booleanState(POWERED)));
+ public static final Block LIGHTNING_ROD = register(new Block("lightning_rod", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN)
+ .booleanState(POWERED)
+ .booleanState(WATERLOGGED)));
+ public static final Block POINTED_DRIPSTONE = register(new Block("pointed_dripstone", builder().destroyTime(1.5f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(DRIPSTONE_THICKNESS)
+ .enumState(VERTICAL_DIRECTION, Direction.UP, Direction.DOWN)
+ .booleanState(WATERLOGGED)));
+ public static final Block DRIPSTONE_BLOCK = register(new Block("dripstone_block", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
+ public static final Block CAVE_VINES = register(new Block("cave_vines", builder().pushReaction(PistonBehavior.DESTROY)
+ .intState(AGE_25)
+ .booleanState(BERRIES)));
+ public static final Block CAVE_VINES_PLANT = register(new Block("cave_vines_plant", builder().pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.GLOW_BERRIES)
+ .booleanState(BERRIES)));
+ public static final Block SPORE_BLOSSOM = register(new Block("spore_blossom", builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block AZALEA = register(new Block("azalea", builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block FLOWERING_AZALEA = register(new Block("flowering_azalea", builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block MOSS_CARPET = register(new Block("moss_carpet", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY)));
+ public static final Block PINK_PETALS = register(new Block("pink_petals", builder().pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .intState(FLOWER_AMOUNT)));
+ public static final Block MOSS_BLOCK = register(new Block("moss_block", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY)));
+ public static final Block BIG_DRIPLEAF = register(new Block("big_dripleaf", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(TILT)
+ .booleanState(WATERLOGGED)));
+ public static final Block BIG_DRIPLEAF_STEM = register(new Block("big_dripleaf_stem", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(WATERLOGGED)));
+ public static final Block SMALL_DRIPLEAF = register(new Block("small_dripleaf", builder().pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(DOUBLE_BLOCK_HALF)
+ .booleanState(WATERLOGGED)));
+ public static final Block HANGING_ROOTS = register(new Block("hanging_roots", builder().pushReaction(PistonBehavior.DESTROY)
+ .booleanState(WATERLOGGED)));
+ public static final Block ROOTED_DIRT = register(new Block("rooted_dirt", builder().destroyTime(0.5f)));
+ public static final Block MUD = register(new Block("mud", builder().destroyTime(0.5f)));
+ public static final Block DEEPSLATE = register(new Block("deepslate", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block COBBLED_DEEPSLATE = register(new Block("cobbled_deepslate", builder().requiresCorrectToolForDrops().destroyTime(3.5f)));
+ public static final Block COBBLED_DEEPSLATE_STAIRS = register(new Block("cobbled_deepslate_stairs", builder().requiresCorrectToolForDrops().destroyTime(3.5f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block COBBLED_DEEPSLATE_SLAB = register(new Block("cobbled_deepslate_slab", builder().requiresCorrectToolForDrops().destroyTime(3.5f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block COBBLED_DEEPSLATE_WALL = register(new Block("cobbled_deepslate_wall", builder().requiresCorrectToolForDrops().destroyTime(3.5f)
+ .enumState(EAST_WALL)
+ .enumState(NORTH_WALL)
+ .enumState(SOUTH_WALL)
+ .booleanState(UP)
+ .booleanState(WATERLOGGED)
+ .enumState(WEST_WALL)));
+ public static final Block POLISHED_DEEPSLATE = register(new Block("polished_deepslate", builder().requiresCorrectToolForDrops().destroyTime(3.5f)));
+ public static final Block POLISHED_DEEPSLATE_STAIRS = register(new Block("polished_deepslate_stairs", builder().requiresCorrectToolForDrops().destroyTime(3.5f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block POLISHED_DEEPSLATE_SLAB = register(new Block("polished_deepslate_slab", builder().requiresCorrectToolForDrops().destroyTime(3.5f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block POLISHED_DEEPSLATE_WALL = register(new Block("polished_deepslate_wall", builder().requiresCorrectToolForDrops().destroyTime(3.5f)
+ .enumState(EAST_WALL)
+ .enumState(NORTH_WALL)
+ .enumState(SOUTH_WALL)
+ .booleanState(UP)
+ .booleanState(WATERLOGGED)
+ .enumState(WEST_WALL)));
+ public static final Block DEEPSLATE_TILES = register(new Block("deepslate_tiles", builder().requiresCorrectToolForDrops().destroyTime(3.5f)));
+ public static final Block DEEPSLATE_TILE_STAIRS = register(new Block("deepslate_tile_stairs", builder().requiresCorrectToolForDrops().destroyTime(3.5f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block DEEPSLATE_TILE_SLAB = register(new Block("deepslate_tile_slab", builder().requiresCorrectToolForDrops().destroyTime(3.5f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block DEEPSLATE_TILE_WALL = register(new Block("deepslate_tile_wall", builder().requiresCorrectToolForDrops().destroyTime(3.5f)
+ .enumState(EAST_WALL)
+ .enumState(NORTH_WALL)
+ .enumState(SOUTH_WALL)
+ .booleanState(UP)
+ .booleanState(WATERLOGGED)
+ .enumState(WEST_WALL)));
+ public static final Block DEEPSLATE_BRICKS = register(new Block("deepslate_bricks", builder().requiresCorrectToolForDrops().destroyTime(3.5f)));
+ public static final Block DEEPSLATE_BRICK_STAIRS = register(new Block("deepslate_brick_stairs", builder().requiresCorrectToolForDrops().destroyTime(3.5f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block DEEPSLATE_BRICK_SLAB = register(new Block("deepslate_brick_slab", builder().requiresCorrectToolForDrops().destroyTime(3.5f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block DEEPSLATE_BRICK_WALL = register(new Block("deepslate_brick_wall", builder().requiresCorrectToolForDrops().destroyTime(3.5f)
+ .enumState(EAST_WALL)
+ .enumState(NORTH_WALL)
+ .enumState(SOUTH_WALL)
+ .booleanState(UP)
+ .booleanState(WATERLOGGED)
+ .enumState(WEST_WALL)));
+ public static final Block CHISELED_DEEPSLATE = register(new Block("chiseled_deepslate", builder().requiresCorrectToolForDrops().destroyTime(3.5f)));
+ public static final Block CRACKED_DEEPSLATE_BRICKS = register(new Block("cracked_deepslate_bricks", builder().requiresCorrectToolForDrops().destroyTime(3.5f)));
+ public static final Block CRACKED_DEEPSLATE_TILES = register(new Block("cracked_deepslate_tiles", builder().requiresCorrectToolForDrops().destroyTime(3.5f)));
+ public static final Block INFESTED_DEEPSLATE = register(new Block("infested_deepslate", builder().destroyTime(1.5f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block SMOOTH_BASALT = register(new Block("smooth_basalt", builder().requiresCorrectToolForDrops().destroyTime(1.25f)));
+ public static final Block RAW_IRON_BLOCK = register(new Block("raw_iron_block", builder().requiresCorrectToolForDrops().destroyTime(5.0f)));
+ public static final Block RAW_COPPER_BLOCK = register(new Block("raw_copper_block", builder().requiresCorrectToolForDrops().destroyTime(5.0f)));
+ public static final Block RAW_GOLD_BLOCK = register(new Block("raw_gold_block", builder().requiresCorrectToolForDrops().destroyTime(5.0f)));
+ public static final Block POTTED_AZALEA_BUSH = register(new FlowerPotBlock("potted_azalea_bush", AZALEA, builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block POTTED_FLOWERING_AZALEA_BUSH = register(new FlowerPotBlock("potted_flowering_azalea_bush", FLOWERING_AZALEA, builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block OCHRE_FROGLIGHT = register(new Block("ochre_froglight", builder().destroyTime(0.3f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block VERDANT_FROGLIGHT = register(new Block("verdant_froglight", builder().destroyTime(0.3f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block PEARLESCENT_FROGLIGHT = register(new Block("pearlescent_froglight", builder().destroyTime(0.3f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block FROGSPAWN = register(new Block("frogspawn", builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block REINFORCED_DEEPSLATE = register(new Block("reinforced_deepslate", builder().destroyTime(55.0f)));
+ public static final Block DECORATED_POT = register(new Block("decorated_pot", builder().setBlockEntity(BlockEntityType.DECORATED_POT).pushReaction(PistonBehavior.DESTROY)
+ .booleanState(CRACKED)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(WATERLOGGED)));
+ public static final Block CRAFTER = register(new Block("crafter", builder().setBlockEntity(BlockEntityType.CRAFTER).destroyTime(1.5f)
+ .booleanState(CRAFTING)
+ .enumState(ORIENTATION, FrontAndTop.VALUES)
+ .booleanState(TRIGGERED)));
+ public static final Block TRIAL_SPAWNER = register(new Block("trial_spawner", builder().setBlockEntity(BlockEntityType.TRIAL_SPAWNER).destroyTime(50.0f)
+ .booleanState(OMINOUS)
+ .enumState(TRIAL_SPAWNER_STATE)));
+ public static final Block VAULT = register(new Block("vault", builder().setBlockEntity(BlockEntityType.VAULT).destroyTime(50.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(OMINOUS)
+ .enumState(VAULT_STATE)));
+ public static final Block HEAVY_CORE = register(new Block("heavy_core", builder().destroyTime(10.0f)
+ .booleanState(WATERLOGGED)));
+
+ private static T register(T block) {
+ block.setJavaId(BlockRegistries.JAVA_BLOCKS.get().size());
+ BlockRegistries.JAVA_BLOCKS.get().add(block);
+ return block;
+ }
+
+ private Blocks() {
+ }
+}
diff --git a/core/src/main/java/org/geysermc/geyser/level/block/GeyserJavaBlockState.java b/core/src/main/java/org/geysermc/geyser/level/block/GeyserJavaBlockState.java
index 8028a4355..782f664fc 100644
--- a/core/src/main/java/org/geysermc/geyser/level/block/GeyserJavaBlockState.java
+++ b/core/src/main/java/org/geysermc/geyser/level/block/GeyserJavaBlockState.java
@@ -16,7 +16,6 @@ public class GeyserJavaBlockState implements JavaBlockState {
boolean canBreakWithHand;
String pickItem;
String pistonBehavior;
- boolean hasBlockEntity;
private GeyserJavaBlockState(Builder builder) {
this.identifier = builder.identifier;
@@ -28,7 +27,6 @@ public class GeyserJavaBlockState implements JavaBlockState {
this.canBreakWithHand = builder.canBreakWithHand;
this.pickItem = builder.pickItem;
this.pistonBehavior = builder.pistonBehavior;
- this.hasBlockEntity = builder.hasBlockEntity;
}
@Override
@@ -76,9 +74,10 @@ public class GeyserJavaBlockState implements JavaBlockState {
return pistonBehavior;
}
+ @SuppressWarnings("removal")
@Override
public boolean hasBlockEntity() {
- return hasBlockEntity;
+ return false;
}
public static class Builder implements JavaBlockState.Builder {
@@ -91,7 +90,6 @@ public class GeyserJavaBlockState implements JavaBlockState {
private boolean canBreakWithHand;
private String pickItem;
private String pistonBehavior;
- private boolean hasBlockEntity;
@Override
public Builder identifier(@NonNull String identifier) {
@@ -147,9 +145,13 @@ public class GeyserJavaBlockState implements JavaBlockState {
return this;
}
+ @SuppressWarnings("removal")
@Override
public Builder hasBlockEntity(boolean hasBlockEntity) {
- this.hasBlockEntity = hasBlockEntity;
+ // keep the current behavior
+ if (this.pistonBehavior == null && hasBlockEntity) {
+ this.pistonBehavior = "BLOCK";
+ }
return this;
}
diff --git a/core/src/main/java/org/geysermc/geyser/level/block/property/BasicEnumProperty.java b/core/src/main/java/org/geysermc/geyser/level/block/property/BasicEnumProperty.java
new file mode 100644
index 000000000..c34392504
--- /dev/null
+++ b/core/src/main/java/org/geysermc/geyser/level/block/property/BasicEnumProperty.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2024 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.level.block.property;
+
+import java.util.List;
+
+/**
+ * Represents enums we don't need classes for in Geyser.
+ */
+public final class BasicEnumProperty extends Property {
+ private final List values;
+
+ private BasicEnumProperty(String name, List values) {
+ super(name);
+ this.values = values;
+ }
+
+ @Override
+ public int valuesCount() {
+ return this.values.size();
+ }
+
+ @Override
+ public int indexOf(String value) {
+ int index = this.values.indexOf(value);
+ if (index == -1) {
+ throw new IllegalArgumentException("Property " + this + " does not have value " + value);
+ }
+ return index;
+ }
+
+ @SuppressWarnings("unchecked")
+ public T values() {
+ return (T) this.values;
+ }
+
+ public static BasicEnumProperty create(String name, String... values) {
+ return new BasicEnumProperty(name, List.of(values));
+ }
+}
diff --git a/core/src/main/java/org/geysermc/geyser/level/block/property/BooleanProperty.java b/core/src/main/java/org/geysermc/geyser/level/block/property/BooleanProperty.java
new file mode 100644
index 000000000..56877f537
--- /dev/null
+++ b/core/src/main/java/org/geysermc/geyser/level/block/property/BooleanProperty.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2024 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.level.block.property;
+
+public final class BooleanProperty extends Property {
+ private BooleanProperty(String name) {
+ super(name);
+ }
+
+ @Override
+ public int valuesCount() {
+ return 2;
+ }
+
+ @Override
+ public int indexOf(Boolean value) {
+ return value ? 0 : 1;
+ }
+
+ public static BooleanProperty create(String name) {
+ return new BooleanProperty(name);
+ }
+}
diff --git a/core/src/main/java/org/geysermc/geyser/level/block/property/ChestType.java b/core/src/main/java/org/geysermc/geyser/level/block/property/ChestType.java
new file mode 100644
index 000000000..c206f127c
--- /dev/null
+++ b/core/src/main/java/org/geysermc/geyser/level/block/property/ChestType.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2024 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.level.block.property;
+
+public enum ChestType {
+ SINGLE,
+ LEFT,
+ RIGHT;
+
+ public static final ChestType[] VALUES = values();
+}
diff --git a/core/src/main/java/org/geysermc/geyser/level/block/property/EnumProperty.java b/core/src/main/java/org/geysermc/geyser/level/block/property/EnumProperty.java
new file mode 100644
index 000000000..e31f665f9
--- /dev/null
+++ b/core/src/main/java/org/geysermc/geyser/level/block/property/EnumProperty.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2024 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.level.block.property;
+
+import it.unimi.dsi.fastutil.ints.IntArrayList;
+import it.unimi.dsi.fastutil.ints.IntList;
+
+public final class EnumProperty> extends Property {
+ private final IntList ordinalValues;
+
+ /**
+ * @param values all possible values of this enum.
+ */
+ private EnumProperty(String name, T[] values) {
+ super(name);
+ this.ordinalValues = new IntArrayList(values.length);
+ for (T anEnum : values) {
+ this.ordinalValues.add(anEnum.ordinal());
+ }
+ }
+
+ @Override
+ public int valuesCount() {
+ return this.ordinalValues.size();
+ }
+
+ @Override
+ public int indexOf(T value) {
+ return this.ordinalValues.indexOf(value.ordinal());
+ }
+
+ @SafeVarargs
+ public static > EnumProperty create(String name, T... values) {
+ return new EnumProperty<>(name, values);
+ }
+}
diff --git a/core/src/main/java/org/geysermc/geyser/level/block/property/FrontAndTop.java b/core/src/main/java/org/geysermc/geyser/level/block/property/FrontAndTop.java
new file mode 100644
index 000000000..e674ac424
--- /dev/null
+++ b/core/src/main/java/org/geysermc/geyser/level/block/property/FrontAndTop.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2024 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.level.block.property;
+
+import org.geysermc.geyser.level.physics.Direction;
+
+public enum FrontAndTop {
+ DOWN_EAST(Direction.DOWN),
+ DOWN_NORTH(Direction.DOWN),
+ DOWN_SOUTH(Direction.DOWN),
+ DOWN_WEST(Direction.DOWN),
+ UP_EAST(Direction.UP),
+ UP_NORTH(Direction.UP),
+ UP_SOUTH(Direction.UP),
+ UP_WEST(Direction.UP),
+ WEST_UP(Direction.WEST),
+ EAST_UP(Direction.EAST),
+ NORTH_UP(Direction.NORTH),
+ SOUTH_UP(Direction.SOUTH);
+
+ private final boolean horizontal;
+
+ FrontAndTop(Direction front) {
+ this.horizontal = front.isHorizontal();
+ }
+
+ public boolean isHorizontal() {
+ return horizontal;
+ }
+
+ public static final FrontAndTop[] VALUES = values();
+}
diff --git a/core/src/main/java/org/geysermc/geyser/level/block/property/IntegerProperty.java b/core/src/main/java/org/geysermc/geyser/level/block/property/IntegerProperty.java
new file mode 100644
index 000000000..a772f414d
--- /dev/null
+++ b/core/src/main/java/org/geysermc/geyser/level/block/property/IntegerProperty.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2024 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.level.block.property;
+
+public final class IntegerProperty extends Property {
+ private final int offset;
+ private final int valuesCount;
+
+ private IntegerProperty(String name, int low, int high) {
+ super(name);
+ this.offset = low;
+ this.valuesCount = high - low;
+ }
+
+ @Override
+ public int valuesCount() {
+ return this.valuesCount;
+ }
+
+ @Override
+ public int indexOf(Integer value) {
+ return value - this.offset;
+ }
+
+ public int low() {
+ return this.offset;
+ }
+
+ public int high() {
+ return this.offset + this.valuesCount;
+ }
+
+ public static IntegerProperty create(String name, int low, int high) {
+ return new IntegerProperty(name, low, high);
+ }
+}
diff --git a/core/src/main/java/org/geysermc/geyser/level/block/property/Properties.java b/core/src/main/java/org/geysermc/geyser/level/block/property/Properties.java
new file mode 100644
index 000000000..7efa2ef80
--- /dev/null
+++ b/core/src/main/java/org/geysermc/geyser/level/block/property/Properties.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2024 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.level.block.property;
+
+import org.geysermc.geyser.level.physics.Axis;
+import org.geysermc.geyser.level.physics.Direction;
+
+public final class Properties {
+ public static final BooleanProperty ATTACHED = BooleanProperty.create("attached");
+ public static final BooleanProperty BOTTOM = BooleanProperty.create("bottom");
+ public static final BooleanProperty CONDITIONAL = BooleanProperty.create("conditional");
+ public static final BooleanProperty DISARMED = BooleanProperty.create("disarmed");
+ public static final BooleanProperty DRAG = BooleanProperty.create("drag");
+ public static final BooleanProperty ENABLED = BooleanProperty.create("enabled");
+ public static final BooleanProperty EXTENDED = BooleanProperty.create("extended");
+ public static final BooleanProperty EYE = BooleanProperty.create("eye");
+ public static final BooleanProperty FALLING = BooleanProperty.create("falling");
+ public static final BooleanProperty HANGING = BooleanProperty.create("hanging");
+ public static final BooleanProperty HAS_BOTTLE_0 = BooleanProperty.create("has_bottle_0");
+ public static final BooleanProperty HAS_BOTTLE_1 = BooleanProperty.create("has_bottle_1");
+ public static final BooleanProperty HAS_BOTTLE_2 = BooleanProperty.create("has_bottle_2");
+ public static final BooleanProperty HAS_RECORD = BooleanProperty.create("has_record");
+ public static final BooleanProperty HAS_BOOK = BooleanProperty.create("has_book");
+ public static final BooleanProperty INVERTED = BooleanProperty.create("inverted");
+ public static final BooleanProperty IN_WALL = BooleanProperty.create("in_wall");
+ public static final BooleanProperty LIT = BooleanProperty.create("lit");
+ public static final BooleanProperty LOCKED = BooleanProperty.create("locked");
+ public static final BooleanProperty OCCUPIED = BooleanProperty.create("occupied");
+ public static final BooleanProperty OPEN = BooleanProperty.create("open");
+ public static final BooleanProperty PERSISTENT = BooleanProperty.create("persistent");
+ public static final BooleanProperty POWERED = BooleanProperty.create("powered");
+ public static final BooleanProperty SHORT = BooleanProperty.create("short");
+ public static final BooleanProperty SIGNAL_FIRE = BooleanProperty.create("signal_fire");
+ public static final BooleanProperty SNOWY = BooleanProperty.create("snowy");
+ public static final BooleanProperty TRIGGERED = BooleanProperty.create("triggered");
+ public static final BooleanProperty UNSTABLE = BooleanProperty.create("unstable");
+ public static final BooleanProperty WATERLOGGED = BooleanProperty.create("waterlogged");
+ public static final BooleanProperty BERRIES = BooleanProperty.create("berries");
+ public static final BooleanProperty BLOOM = BooleanProperty.create("bloom");
+ public static final BooleanProperty SHRIEKING = BooleanProperty.create("shrieking");
+ public static final BooleanProperty CAN_SUMMON = BooleanProperty.create("can_summon");
+ public static final EnumProperty HORIZONTAL_AXIS = EnumProperty.create("axis", Axis.X, Axis.Z);
+ public static final EnumProperty AXIS = EnumProperty.create("axis", Axis.VALUES);
+ public static final BooleanProperty UP = BooleanProperty.create("up");
+ public static final BooleanProperty DOWN = BooleanProperty.create("down");
+ public static final BooleanProperty NORTH = BooleanProperty.create("north");
+ public static final BooleanProperty EAST = BooleanProperty.create("east");
+ public static final BooleanProperty SOUTH = BooleanProperty.create("south");
+ public static final BooleanProperty WEST = BooleanProperty.create("west");
+ public static final EnumProperty FACING = EnumProperty.create("facing", Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN);
+ public static final EnumProperty FACING_HOPPER = EnumProperty.create("facing", Direction.DOWN, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST);
+ public static final EnumProperty HORIZONTAL_FACING = EnumProperty.create("facing", Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST);
+ public static final IntegerProperty FLOWER_AMOUNT = IntegerProperty.create("flower_amount", 1, 4);
+ public static final EnumProperty ORIENTATION = EnumProperty.create("orientation", FrontAndTop.VALUES);
+ public static final BasicEnumProperty ATTACH_FACE = BasicEnumProperty.create("face", "floor", "wall", "ceiling");
+ public static final BasicEnumProperty BELL_ATTACHMENT = BasicEnumProperty.create("attachment", "floor", "ceiling", "single_wall", "double_wall");
+ public static final BasicEnumProperty EAST_WALL = BasicEnumProperty.create("east", "none", "low", "tall");
+ public static final BasicEnumProperty NORTH_WALL = BasicEnumProperty.create("north", "none", "low", "tall");
+ public static final BasicEnumProperty SOUTH_WALL = BasicEnumProperty.create("south", "none", "low", "tall");
+ public static final BasicEnumProperty WEST_WALL = BasicEnumProperty.create("west", "none", "low", "tall");
+ public static final BasicEnumProperty EAST_REDSTONE = BasicEnumProperty.create("east", "up", "side", "none");
+ public static final BasicEnumProperty NORTH_REDSTONE = BasicEnumProperty.create("north", "up", "side", "none");
+ public static final BasicEnumProperty SOUTH_REDSTONE = BasicEnumProperty.create("south", "up", "side", "none");
+ public static final BasicEnumProperty WEST_REDSTONE = BasicEnumProperty.create("west", "up", "side", "none");
+ public static final BasicEnumProperty DOUBLE_BLOCK_HALF = BasicEnumProperty.create("half", "upper", "lower");
+ public static final BasicEnumProperty HALF = BasicEnumProperty.create("half", "top", "bottom");
+ public static final BasicEnumProperty RAIL_SHAPE = BasicEnumProperty.create("shape", "north_south", "east_west", "ascending_east", "ascending_west", "ascending_north", "ascending_south", "south_east", "south_west", "north_west", "north_east");
+ public static final BasicEnumProperty RAIL_SHAPE_STRAIGHT = BasicEnumProperty.create("shape", "north_south", "east_west", "ascending_east", "ascending_west", "ascending_north", "ascending_south");
+ public static final IntegerProperty AGE_1 = IntegerProperty.create("age", 0, 1);
+ public static final IntegerProperty AGE_2 = IntegerProperty.create("age", 0, 2);
+ public static final IntegerProperty AGE_3 = IntegerProperty.create("age", 0, 3);
+ public static final IntegerProperty AGE_4 = IntegerProperty.create("age", 0, 4);
+ public static final IntegerProperty AGE_5 = IntegerProperty.create("age", 0, 5);
+ public static final IntegerProperty AGE_7 = IntegerProperty.create("age", 0, 7);
+ public static final IntegerProperty AGE_15 = IntegerProperty.create("age", 0, 15);
+ public static final IntegerProperty AGE_25 = IntegerProperty.create("age", 0, 25);
+ public static final IntegerProperty BITES = IntegerProperty.create("bites", 0, 6);
+ public static final IntegerProperty CANDLES = IntegerProperty.create("candles", 1, 4);
+ public static final IntegerProperty DELAY = IntegerProperty.create("delay", 1, 4);
+ public static final IntegerProperty DISTANCE = IntegerProperty.create("distance", 1, 7);
+ public static final IntegerProperty EGGS = IntegerProperty.create("eggs", 1, 4);
+ public static final IntegerProperty HATCH = IntegerProperty.create("hatch", 0, 2);
+ public static final IntegerProperty LAYERS = IntegerProperty.create("layers", 1, 8);
+ public static final IntegerProperty LEVEL_CAULDRON = IntegerProperty.create("level", 1, 3);
+ public static final IntegerProperty LEVEL_COMPOSTER = IntegerProperty.create("level", 0, 8);
+ public static final IntegerProperty LEVEL_FLOWING = IntegerProperty.create("level", 1, 8);
+ public static final IntegerProperty LEVEL_HONEY = IntegerProperty.create("honey_level", 0, 5);
+ public static final IntegerProperty LEVEL = IntegerProperty.create("level", 0, 15);
+ public static final IntegerProperty MOISTURE = IntegerProperty.create("moisture", 0, 7);
+ public static final IntegerProperty NOTE = IntegerProperty.create("note", 0, 24);
+ public static final IntegerProperty PICKLES = IntegerProperty.create("pickles", 1, 4);
+ public static final IntegerProperty POWER = IntegerProperty.create("power", 0, 15);
+ public static final IntegerProperty STAGE = IntegerProperty.create("stage", 0, 1);
+ public static final IntegerProperty STABILITY_DISTANCE = IntegerProperty.create("distance", 0, 7);
+ public static final IntegerProperty RESPAWN_ANCHOR_CHARGES = IntegerProperty.create("charges", 0, 4);
+ public static final IntegerProperty ROTATION_16 = IntegerProperty.create("rotation", 0, 15);
+ public static final BasicEnumProperty BED_PART = BasicEnumProperty.create("part", "head", "foot");
+ public static final EnumProperty CHEST_TYPE = EnumProperty.create("type", ChestType.VALUES);
+ public static final BasicEnumProperty MODE_COMPARATOR = BasicEnumProperty.create("mode", "compare", "subtract");
+ public static final BasicEnumProperty DOOR_HINGE = BasicEnumProperty.create("hinge", "left", "right");
+ public static final BasicEnumProperty NOTEBLOCK_INSTRUMENT = BasicEnumProperty.create("instrument", "harp", "basedrum", "snare", "hat", "bass", "flute", "bell", "guitar", "chime", "xylophone", "iron_xylophone", "cow_bell", "didgeridoo", "bit", "banjo", "pling", "zombie", "skeleton", "creeper", "dragon", "wither_skeleton", "piglin", "custom_head");
+ public static final BasicEnumProperty PISTON_TYPE = BasicEnumProperty.create("type", "normal", "sticky");
+ public static final BasicEnumProperty SLAB_TYPE = BasicEnumProperty.create("type", "top", "bottom", "double");
+ public static final BasicEnumProperty STAIRS_SHAPE = BasicEnumProperty.create("shape", "straight", "inner_left", "inner_right", "outer_left", "outer_right");
+ public static final BasicEnumProperty STRUCTUREBLOCK_MODE = BasicEnumProperty.create("mode", "save", "load", "corner", "data");
+ public static final BasicEnumProperty BAMBOO_LEAVES = BasicEnumProperty.create("leaves", "none", "small", "large");
+ public static final BasicEnumProperty TILT = BasicEnumProperty.create("tilt", "none", "unstable", "partial", "full");
+ public static final EnumProperty VERTICAL_DIRECTION = EnumProperty.create("vertical_direction", Direction.UP, Direction.DOWN);
+ public static final BasicEnumProperty DRIPSTONE_THICKNESS = BasicEnumProperty.create("thickness", "tip_merge", "tip", "frustum", "middle", "base");
+ public static final BasicEnumProperty SCULK_SENSOR_PHASE = BasicEnumProperty.create("sculk_sensor_phase", "inactive", "active", "cooldown");
+ public static final BooleanProperty CHISELED_BOOKSHELF_SLOT_0_OCCUPIED = BooleanProperty.create("slot_0_occupied");
+ public static final BooleanProperty CHISELED_BOOKSHELF_SLOT_1_OCCUPIED = BooleanProperty.create("slot_1_occupied");
+ public static final BooleanProperty CHISELED_BOOKSHELF_SLOT_2_OCCUPIED = BooleanProperty.create("slot_2_occupied");
+ public static final BooleanProperty CHISELED_BOOKSHELF_SLOT_3_OCCUPIED = BooleanProperty.create("slot_3_occupied");
+ public static final BooleanProperty CHISELED_BOOKSHELF_SLOT_4_OCCUPIED = BooleanProperty.create("slot_4_occupied");
+ public static final BooleanProperty CHISELED_BOOKSHELF_SLOT_5_OCCUPIED = BooleanProperty.create("slot_5_occupied");
+ public static final IntegerProperty DUSTED = IntegerProperty.create("dusted", 0, 3);
+ public static final BooleanProperty CRACKED = BooleanProperty.create("cracked");
+ public static final BooleanProperty CRAFTING = BooleanProperty.create("crafting");
+ public static final BasicEnumProperty TRIAL_SPAWNER_STATE = BasicEnumProperty.create("trial_spawner_state", "inactive", "waiting_for_players", "active", "waiting_for_reward_ejection", "ejecting_reward", "cooldown");
+ public static final BasicEnumProperty VAULT_STATE = BasicEnumProperty.create("vault_state", "inactive", "active", "unlocking", "ejecting");
+ public static final BooleanProperty OMINOUS = BooleanProperty.create("ominous");
+}
diff --git a/core/src/main/java/org/geysermc/geyser/level/block/property/Property.java b/core/src/main/java/org/geysermc/geyser/level/block/property/Property.java
new file mode 100644
index 000000000..0c4713124
--- /dev/null
+++ b/core/src/main/java/org/geysermc/geyser/level/block/property/Property.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2024 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.level.block.property;
+
+public abstract class Property> {
+ private final String name;
+
+ protected Property(String name) {
+ this.name = name;
+ }
+
+ public String name() {
+ return name;
+ }
+
+ public abstract int valuesCount();
+
+ public abstract int indexOf(T value);
+
+ @Override
+ public String toString() {
+ return getClass().getSimpleName() + "[" + name + "]";
+ }
+}
diff --git a/core/src/main/java/org/geysermc/geyser/registry/type/EnchantmentData.java b/core/src/main/java/org/geysermc/geyser/level/block/type/BannerBlock.java
similarity index 74%
rename from core/src/main/java/org/geysermc/geyser/registry/type/EnchantmentData.java
rename to core/src/main/java/org/geysermc/geyser/level/block/type/BannerBlock.java
index 970e128a4..481004baa 100644
--- a/core/src/main/java/org/geysermc/geyser/registry/type/EnchantmentData.java
+++ b/core/src/main/java/org/geysermc/geyser/level/block/type/BannerBlock.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
+ * Copyright (c) 2024 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
@@ -23,13 +23,17 @@
* @link https://github.com/GeyserMC/Geyser
*/
-package org.geysermc.geyser.registry.type;
+package org.geysermc.geyser.level.block.type;
-import it.unimi.dsi.fastutil.ints.IntSet;
-import org.geysermc.geyser.inventory.item.Enchantment.JavaEnchantment;
+public class BannerBlock extends Block {
+ private final int dyeColor;
-import java.util.Set;
+ public BannerBlock(String javaIdentifier, int dyeColor, Builder builder) {
+ super(javaIdentifier, builder);
+ this.dyeColor = dyeColor;
+ }
-public record EnchantmentData(int rarityMultiplier, int maxLevel, Set incompatibleEnchantments,
- IntSet validItems) {
+ public int dyeColor() {
+ return dyeColor;
+ }
}
diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/BedBlock.java b/core/src/main/java/org/geysermc/geyser/level/block/type/BedBlock.java
new file mode 100644
index 000000000..e72dbdafa
--- /dev/null
+++ b/core/src/main/java/org/geysermc/geyser/level/block/type/BedBlock.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2024 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.level.block.type;
+
+public class BedBlock extends Block {
+ private final int dyeColor;
+
+ public BedBlock(String javaIdentifier, int dyeColor, Builder builder) {
+ super(javaIdentifier, builder);
+ this.dyeColor = dyeColor;
+ }
+
+ public int dyeColor() {
+ return dyeColor;
+ }
+}
diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/Block.java b/core/src/main/java/org/geysermc/geyser/level/block/type/Block.java
new file mode 100644
index 000000000..a005fc103
--- /dev/null
+++ b/core/src/main/java/org/geysermc/geyser/level/block/type/Block.java
@@ -0,0 +1,362 @@
+/*
+ * Copyright (c) 2024 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.level.block.type;
+
+import it.unimi.dsi.fastutil.ints.IntArrayList;
+import it.unimi.dsi.fastutil.ints.IntList;
+import net.kyori.adventure.key.Key;
+import org.checkerframework.checker.nullness.qual.NonNull;
+import org.checkerframework.checker.nullness.qual.Nullable;
+import org.cloudburstmc.math.vector.Vector3i;
+import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition;
+import org.cloudburstmc.protocol.bedrock.packet.UpdateBlockPacket;
+import org.geysermc.geyser.item.type.Item;
+import org.geysermc.geyser.level.block.Blocks;
+import org.geysermc.geyser.level.block.property.BasicEnumProperty;
+import org.geysermc.geyser.level.block.property.IntegerProperty;
+import org.geysermc.geyser.level.block.property.Property;
+import org.geysermc.geyser.level.physics.PistonBehavior;
+import org.geysermc.geyser.registry.BlockRegistries;
+import org.geysermc.geyser.session.GeyserSession;
+import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack;
+import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType;
+import org.intellij.lang.annotations.Subst;
+
+import java.util.*;
+import java.util.function.Supplier;
+import java.util.stream.Stream;
+
+public class Block {
+ public static final int JAVA_AIR_ID = 0;
+
+ private final Key javaIdentifier;
+ /**
+ * Can you harvest this with your hand.
+ */
+ private final boolean requiresCorrectToolForDrops;
+ private final @Nullable BlockEntityType blockEntityType;
+ private final float destroyTime;
+ private final @NonNull PistonBehavior pushReaction;
+ /**
+ * Used for classes we don't have implemented yet that override Mojmap getCloneItemStack with their own item.
+ * A supplier prevents any issues arising where the Items class finishes before the Blocks class.
+ */
+ private final Supplier pickItem;
+ protected Item item = null;
+ private int javaId = -1;
+
+ /**
+ * Used for switching a given block state to different states.
+ */
+ private final Property>[] propertyKeys;
+ private final BlockState defaultState;
+
+ public Block(@Subst("empty") String javaIdentifier, Builder builder) {
+ this.javaIdentifier = Key.key(javaIdentifier);
+ this.requiresCorrectToolForDrops = builder.requiresCorrectToolForDrops;
+ this.blockEntityType = builder.blockEntityType;
+ this.destroyTime = builder.destroyTime;
+ this.pushReaction = builder.pushReaction;
+ this.pickItem = builder.pickItem;
+
+ BlockState firstState = builder.build(this).get(0);
+ this.propertyKeys = builder.propertyKeys; // Ensure this is not null before iterating over states
+ this.defaultState = setDefaultState(firstState);
+ }
+
+ public void updateBlock(GeyserSession session, BlockState state, Vector3i position) {
+ checkForEmptySkull(session, state, position);
+
+ BlockDefinition definition = session.getBlockMappings().getBedrockBlock(state);
+ sendBlockUpdatePacket(session, state, definition, position);
+
+ // Extended collision boxes for custom blocks
+ if (!session.getBlockMappings().getExtendedCollisionBoxes().isEmpty()) {
+ int aboveBlock = session.getGeyser().getWorldManager().getBlockAt(session, position.getX(), position.getY() + 1, position.getZ());
+ BlockDefinition aboveBedrockExtendedCollisionDefinition = session.getBlockMappings().getExtendedCollisionBoxes().get(state.javaId());
+ int belowBlock = session.getGeyser().getWorldManager().getBlockAt(session, position.getX(), position.getY() - 1, position.getZ());
+ BlockDefinition belowBedrockExtendedCollisionDefinition = session.getBlockMappings().getExtendedCollisionBoxes().get(belowBlock);
+ if (belowBedrockExtendedCollisionDefinition != null && state.is(Blocks.AIR)) {
+ UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket();
+ updateBlockPacket.setDataLayer(0);
+ updateBlockPacket.setBlockPosition(position);
+ updateBlockPacket.setDefinition(belowBedrockExtendedCollisionDefinition);
+ updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NETWORK);
+ session.sendUpstreamPacket(updateBlockPacket);
+ } else if (aboveBedrockExtendedCollisionDefinition != null && aboveBlock == Block.JAVA_AIR_ID) {
+ UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket();
+ updateBlockPacket.setDataLayer(0);
+ updateBlockPacket.setBlockPosition(position.add(0, 1, 0));
+ updateBlockPacket.setDefinition(aboveBedrockExtendedCollisionDefinition);
+ updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NETWORK);
+ session.sendUpstreamPacket(updateBlockPacket);
+ } else if (aboveBlock == Block.JAVA_AIR_ID) {
+ UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket();
+ updateBlockPacket.setDataLayer(0);
+ updateBlockPacket.setBlockPosition(position.add(0, 1, 0));
+ updateBlockPacket.setDefinition(session.getBlockMappings().getBedrockAir());
+ updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NETWORK);
+ session.sendUpstreamPacket(updateBlockPacket);
+ }
+ }
+ }
+
+ protected void sendBlockUpdatePacket(GeyserSession session, BlockState state, BlockDefinition definition, Vector3i position) {
+ UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket();
+ updateBlockPacket.setDataLayer(0);
+ updateBlockPacket.setBlockPosition(position);
+ updateBlockPacket.setDefinition(definition);
+ updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NEIGHBORS);
+ updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NETWORK);
+ session.sendUpstreamPacket(updateBlockPacket);
+
+ UpdateBlockPacket waterPacket = new UpdateBlockPacket();
+ waterPacket.setDataLayer(1);
+ waterPacket.setBlockPosition(position);
+ if (BlockRegistries.WATERLOGGED.get().get(state.javaId())) {
+ waterPacket.setDefinition(session.getBlockMappings().getBedrockWater());
+ } else {
+ waterPacket.setDefinition(session.getBlockMappings().getBedrockAir());
+ }
+ session.sendUpstreamPacket(waterPacket);
+ }
+
+ protected void checkForEmptySkull(GeyserSession session, BlockState state, Vector3i position) {
+ if (!(state.block() instanceof SkullBlock)) {
+ // Skull is gone
+ session.getSkullCache().removeSkull(position);
+ }
+ }
+
+ public Item asItem() {
+ if (this.item == null) {
+ return this.item = Item.byBlock(this);
+ }
+ return this.item;
+ }
+
+ public ItemStack pickItem(BlockState state) {
+ if (this.pickItem != null) {
+ return new ItemStack(this.pickItem.get().javaId());
+ }
+ return new ItemStack(this.asItem().javaId());
+ }
+
+ /**
+ * Should only be ran on block creation. Can be overridden.
+ * @param firstState the first state created from this block
+ */
+ protected BlockState setDefaultState(BlockState firstState) {
+ return firstState;
+ }
+
+ @NonNull
+ public Key javaIdentifier() {
+ return javaIdentifier;
+ }
+
+ public boolean requiresCorrectToolForDrops() {
+ return requiresCorrectToolForDrops;
+ }
+
+ public boolean hasBlockEntity() {
+ return blockEntityType != null;
+ }
+
+ @Nullable
+ public BlockEntityType blockEntityType() {
+ return blockEntityType;
+ }
+
+ public float destroyTime() {
+ return destroyTime;
+ }
+
+ @NonNull
+ public PistonBehavior pushReaction() {
+ return this.pushReaction;
+ }
+
+ public BlockState defaultBlockState() {
+ return this.defaultState;
+ }
+
+ public int javaId() {
+ return javaId;
+ }
+
+ public void setJavaId(int javaId) {
+ if (this.javaId != -1) {
+ throw new RuntimeException("Block ID has already been set!");
+ }
+ this.javaId = javaId;
+ }
+
+ @Override
+ public String toString() {
+ return "Block{" +
+ "javaIdentifier='" + javaIdentifier + '\'' +
+ ", javaId=" + javaId +
+ '}';
+ }
+
+ Property>[] propertyKeys() {
+ return propertyKeys;
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public static final class Builder {
+ private final Map, List>> states = new LinkedHashMap<>();
+ private boolean requiresCorrectToolForDrops = false;
+ private BlockEntityType blockEntityType = null;
+ private PistonBehavior pushReaction = PistonBehavior.NORMAL;
+ private float destroyTime;
+ private Supplier pickItem;
+
+ // We'll use this field after building
+ private Property>[] propertyKeys;
+
+ /**
+ * For states that we're just tracking for mirroring Java states.
+ */
+ public Builder enumState(BasicEnumProperty property) {
+ states.put(property, property.values());
+ return this;
+ }
+
+ @SafeVarargs
+ public final > Builder enumState(Property property, T... enums) {
+ states.put(property, List.of(enums));
+ return this;
+ }
+
+ public Builder booleanState(Property property) {
+ states.put(property, List.of(Boolean.TRUE, Boolean.FALSE)); // Make this list a static constant if it'll survive past initialization
+ return this;
+ }
+
+ public Builder intState(IntegerProperty property) {
+ int low = property.low();
+ int high = property.high();
+ IntList list = new IntArrayList();
+ // There is a state for every number between the low and high.
+ for (int i = low; i <= high; i++) {
+ list.add(i);
+ }
+ states.put(property, List.copyOf(list)); // Boxing reasons for that copy I guess.
+ return this;
+ }
+
+ public Builder requiresCorrectToolForDrops() {
+ this.requiresCorrectToolForDrops = true;
+ return this;
+ }
+
+ public Builder setBlockEntity(BlockEntityType blockEntityType) {
+ this.blockEntityType = blockEntityType;
+ return this;
+ }
+
+ public Builder destroyTime(float destroyTime) {
+ this.destroyTime = destroyTime;
+ return this;
+ }
+
+ public Builder pushReaction(PistonBehavior pushReaction) {
+ this.pushReaction = pushReaction;
+ return this;
+ }
+
+ public Builder pickItem(Supplier pickItem) {
+ this.pickItem = pickItem;
+ return this;
+ }
+
+ private List build(Block block) {
+ if (states.isEmpty()) {
+ BlockState state = new BlockState(block, BlockRegistries.BLOCK_STATES.get().size());
+ BlockRegistries.BLOCK_STATES.get().add(state);
+ propertyKeys = null;
+ return List.of(state);
+ } else if (states.size() == 1) {
+ // We can optimize because we don't need to worry about combinations
+ Map.Entry, List>> property = this.states.entrySet().stream().findFirst().orElseThrow();
+ List states = new ArrayList<>(property.getValue().size());
+ property.getValue().forEach(value -> {
+ BlockState state = new BlockState(block, BlockRegistries.BLOCK_STATES.get().size(), new Comparable[] {value});
+ BlockRegistries.BLOCK_STATES.get().add(state);
+ states.add(state);
+ });
+ this.propertyKeys = new Property[]{property.getKey()};
+ return states;
+ } else {
+ // Think of this stream as another list containing, at the start, one empty list.
+ // It's two collections. Not a stream from the empty list.
+ Stream>> stream = Stream.of(Collections.emptyList());
+ for (var values : this.states.values()) {
+ // OK, so here's how I understand this works. Because this was staring at vanilla Java code trying
+ // to figure out exactly how it works so we don't have any discrepencies.
+ // For each existing pair in the list, a new list is created, adding one of the new values.
+ // Property up [true/false] would exist as true and false
+ // Both entries will get duplicated, adding down, true and false.
+ stream = stream.flatMap(aPreviousPropertiesList ->
+ // So the above is a list. It may be empty if this is the first property,
+ // or it may be populated if this is not the first property.
+ // We're about to create a new stream, each with a new list,
+ // for every previous property
+ values.stream().map(value -> {
+ var newProperties = new ArrayList<>(aPreviousPropertiesList);
+ newProperties.add(value);
+ return newProperties;
+ }));
+ }
+
+ List states = new ArrayList<>();
+ // Now we have a list of Pairs. Each list is a block state!
+ // If we have two boolean properties: up [true/false] and down [true/false],
+ // We'll see [up=true,down=true], [up=false,down=true], [up=true,down=false], [up=false,down=false]
+ List>> result = stream.toList();
+ // Ensure each block state shares the same key array. Creating a keySet here shouldn't be an issue since
+ // this states map should be removed after build.
+ Property>[] keys = this.states.keySet().toArray(new Property>[0]);
+ result.forEach(properties -> {
+ Comparable>[] values = properties.toArray(new Comparable>[0]);
+ BlockState state = new BlockState(block, BlockRegistries.BLOCK_STATES.get().size(), values);
+ BlockRegistries.BLOCK_STATES.get().add(state);
+ states.add(state);
+ });
+ this.propertyKeys = keys;
+ return states;
+ }
+ }
+
+ private Builder() {
+ }
+ }
+}
diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/BlockState.java b/core/src/main/java/org/geysermc/geyser/level/block/type/BlockState.java
new file mode 100644
index 000000000..2513e3ceb
--- /dev/null
+++ b/core/src/main/java/org/geysermc/geyser/level/block/type/BlockState.java
@@ -0,0 +1,198 @@
+/*
+ * Copyright (c) 2024 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.level.block.type;
+
+import org.checkerframework.checker.nullness.qual.NonNull;
+import org.checkerframework.checker.nullness.qual.Nullable;
+import org.geysermc.geyser.level.block.property.Property;
+import org.geysermc.geyser.registry.BlockRegistries;
+
+import java.util.Locale;
+
+public final class BlockState {
+ private final Block block;
+ private final int javaId;
+ /**
+ * The values of each property of this block state. These should be treated as keys to {@link Block#propertyKeys()}.
+ * Of note - the comparable part probably doesn't do anything because we occasionally use strings in place of enums.
+ * Will be null if there's only one block state for a block.
+ */
+ private final Comparable>[] states;
+
+ public BlockState(Block block, int javaId) {
+ this(block, javaId, null);
+ }
+
+ BlockState(Block block, int javaId, Comparable>[] states) {
+ this.block = block;
+ this.javaId = javaId;
+ this.states = states;
+ }
+
+ public > T getValue(Property property) {
+ //noinspection unchecked
+ return (T) get(property);
+ }
+
+ public > T getValueNullable(Property property) {
+ var value = get(property);
+ if (value == null) {
+ return null;
+ }
+ //noinspection unchecked
+ return (T) get(property);
+ }
+
+ public > T getValue(Property property, T def) {
+ var value = get(property);
+ if (value == null) {
+ return def;
+ }
+ //noinspection unchecked
+ return (T) value;
+ }
+
+ @Nullable
+ private Comparable> get(Property> property) {
+ Property>[] keys = this.block.propertyKeys();
+ if (keys == null) {
+ return null;
+ }
+ // We're copying the behavior Reference2ObjectArrayMap uses
+ for (int i = keys.length; i-- != 0;) {
+ if (keys[i] == property) {
+ return this.states[i];
+ }
+ }
+ return null;
+ }
+
+ /**
+ * @return the {@link BlockState} instance with the given value.
+ */
+ public > BlockState withValue(Property property, T value) {
+ Property>[] keys = this.block.propertyKeys();
+ if (keys == null) {
+ throw new IllegalStateException(this + " does not have any different states!");
+ }
+
+ T currentValue = getValue(property);
+ if (currentValue == null) {
+ throw new IllegalArgumentException("This BlockState does not have the property " + property);
+ }
+ if (currentValue.equals(value)) {
+ // No action required. This block state is the state we're looking for.
+ return this;
+ }
+
+ // Diff is how much we will have to traverse as a sort of offset
+
+ // Block states are calculated in a predictable structure:
+ // minecraft:cobblestone_wall[east=none,north=none,south=none,up=true,waterlogged=true,west=none]
+ // minecraft:cobblestone_wall[east=none,north=none,south=none,up=true,waterlogged=true,west=low]
+ // minecraft:cobblestone_wall[east=none,north=none,south=none,up=true,waterlogged=true,west=tall]
+ // minecraft:cobblestone_wall[east=none,north=none,south=none,up=true,waterlogged=false,west=none]
+ // minecraft:cobblestone_wall[east=none,north=none,south=none,up=true,waterlogged=false,west=low]
+ // minecraft:cobblestone_wall[east=none,north=none,south=none,up=true,waterlogged=false,west=tall]
+ // minecraft:cobblestone_wall[east=none,north=none,south=none,up=false,waterlogged=true,west=none]
+
+ // The last value goes through all its iterations, then the next state goes through all its iterations.
+ // West goes none -> low -> tall, then waterlogged is toggled as west cycles again.
+ // Then when waterlogged goes through all its properties, up is toggled, and west goes through again
+ // If we want to find the "up" property in order, then we need to find how many iterations each property
+ // after it goes in. West goes for 3, waterlogged goes for 2. Adding those together, we find that we need to
+ // add five to get to the next toggle of the up property
+ int diff = 0;
+ for (int i = keys.length - 1; i >= 0; i--) {
+ if (keys[i] != property) {
+ diff += keys[i].valuesCount();
+ } else {
+ break;
+ }
+ }
+
+ // How many times do we have to jump by diff? This depends on how far away each value is from each other.
+ // piston_head[facing=north] might be right next to piston_head[facing=south], which just one diff'd hop.
+ // But piston_head[facing=west] is further away, requiring more hops.
+ int thatOffset = property.indexOf(value);
+ int thisOffset = property.indexOf(currentValue);
+ if (diff == 0) {
+ // This can happen if the property is at the tail end of the block and there are no other properties to look through
+ // If we have minecraft:cobblestone_wall[east=none,north=none,south=none,up=true,waterlogged=true,west=none]
+ // And want minecraft:cobblestone_wall[east=none,north=none,south=none,up=true,waterlogged=true,west=low]
+ // The above for loop will always stop at the first break because the last property has already been found
+ diff = 1;
+ }
+ return of(this.javaId + ((thatOffset - thisOffset) * diff));
+ }
+
+ public Block block() {
+ return this.block;
+ }
+
+ public int javaId() {
+ return this.javaId;
+ }
+
+ public boolean is(Block block) {
+ return this.block == block;
+ }
+
+ @Override
+ public String toString() {
+ if (this.states == null) {
+ return this.block.javaIdentifier().toString();
+ }
+ return this.block.javaIdentifier().toString() + "[" + paramsToString() + "]";
+ }
+
+ private String paramsToString() {
+ StringBuilder builder = new StringBuilder();
+ Property>[] propertyKeys = this.block.propertyKeys();
+ if (propertyKeys != null) {
+ for (int i = 0; i < propertyKeys.length; i++) {
+ builder.append(propertyKeys[i].name())
+ .append("=")
+ .append(this.states[i].toString().toLowerCase(Locale.ROOT)); // lowercase covers enums
+ if (i < propertyKeys.length - 1) {
+ builder.append(",");
+ }
+ }
+ }
+ return builder.toString();
+ }
+
+ /**
+ * Null-safe method that looks up a Java block state ID in the BLOCK_STATES registry, and defaults to air if not found.
+ *
+ * @param javaId the Java block state ID to look up.
+ * @return the corresponding block state, or air if the given ID wasn't registered and returned null.
+ */
+ @NonNull
+ public static BlockState of(int javaId) {
+ return BlockRegistries.BLOCK_STATES.getOrDefault(javaId, BlockRegistries.BLOCK_STATES.get(Block.JAVA_AIR_ID));
+ }
+}
diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/CauldronBlock.java b/core/src/main/java/org/geysermc/geyser/level/block/type/CauldronBlock.java
new file mode 100644
index 000000000..d27969af7
--- /dev/null
+++ b/core/src/main/java/org/geysermc/geyser/level/block/type/CauldronBlock.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2024 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.level.block.type;
+
+import org.cloudburstmc.math.vector.Vector3i;
+import org.cloudburstmc.nbt.NbtList;
+import org.cloudburstmc.nbt.NbtMap;
+import org.cloudburstmc.nbt.NbtType;
+import org.geysermc.geyser.session.GeyserSession;
+import org.geysermc.geyser.translator.level.block.entity.BedrockChunkWantsBlockEntityTag;
+import org.geysermc.geyser.translator.level.block.entity.BlockEntityTranslator;
+
+public class CauldronBlock extends Block implements BedrockChunkWantsBlockEntityTag {
+ public CauldronBlock(String javaIdentifier, Builder builder) {
+ super(javaIdentifier, builder);
+ }
+
+ @Override
+ public NbtMap createTag(GeyserSession session, Vector3i position, BlockState blockState) {
+ // As of 1.18.30: this is required to make rendering not look weird on chunk load (lava and snow cauldrons look dim)
+ return BlockEntityTranslator.getConstantBedrockTag("Cauldron", position.getX(), position.getY(), position.getZ())
+ .putByte("isMovable", (byte) 0)
+ .putShort("PotionId", (short) -1)
+ .putShort("PotionType", (short) -1)
+ .putList("Items", NbtType.END, NbtList.EMPTY)
+ .build();
+ }
+}
diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/ChestBlock.java b/core/src/main/java/org/geysermc/geyser/level/block/type/ChestBlock.java
new file mode 100644
index 000000000..69132ccfd
--- /dev/null
+++ b/core/src/main/java/org/geysermc/geyser/level/block/type/ChestBlock.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2024 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.level.block.type;
+
+import org.cloudburstmc.math.vector.Vector3i;
+import org.cloudburstmc.nbt.NbtMapBuilder;
+import org.geysermc.geyser.level.block.property.ChestType;
+import org.geysermc.geyser.level.block.property.Properties;
+import org.geysermc.geyser.session.GeyserSession;
+import org.geysermc.geyser.translator.level.block.entity.BlockEntityTranslator;
+import org.geysermc.geyser.util.BlockEntityUtils;
+import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType;
+
+public class ChestBlock extends Block {
+ public ChestBlock(String javaIdentifier, Builder builder) {
+ super(javaIdentifier, builder);
+ }
+
+ @Override
+ public void updateBlock(GeyserSession session, BlockState state, Vector3i position) {
+ super.updateBlock(session, state, position);
+
+ if (state.getValue(Properties.CHEST_TYPE) != ChestType.SINGLE) {
+ NbtMapBuilder tagBuilder = BlockEntityTranslator.getConstantBedrockTag(BlockEntityType.CHEST, position.getX(), position.getY(), position.getZ());
+ BlockEntityUtils.getBlockEntityTranslator(BlockEntityType.CHEST).translateTag(session, tagBuilder, null, state); //TODO
+ BlockEntityUtils.updateBlockEntity(session, tagBuilder.build(), position);
+ }
+ }
+}
diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/DoorBlock.java b/core/src/main/java/org/geysermc/geyser/level/block/type/DoorBlock.java
new file mode 100644
index 000000000..bfde51a79
--- /dev/null
+++ b/core/src/main/java/org/geysermc/geyser/level/block/type/DoorBlock.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2024 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.level.block.type;
+
+import org.cloudburstmc.math.vector.Vector3i;
+import org.geysermc.geyser.level.block.property.Properties;
+import org.geysermc.geyser.session.GeyserSession;
+import org.geysermc.geyser.util.ChunkUtils;
+
+public class DoorBlock extends Block {
+ public DoorBlock(String javaIdentifier, Builder builder) {
+ super(javaIdentifier, builder);
+ }
+
+ @Override
+ public void updateBlock(GeyserSession session, BlockState state, Vector3i position) {
+ super.updateBlock(session, state, position);
+
+ if (state.getValue(Properties.DOUBLE_BLOCK_HALF).equals("upper")) {
+ // Update the lower door block as Bedrock client doesn't like door to be closed from the top
+ // See https://github.com/GeyserMC/Geyser/issues/4358
+ Vector3i belowDoorPosition = position.sub(0, 1, 0);
+ BlockState belowDoorBlockState = session.getGeyser().getWorldManager().blockAt(session, belowDoorPosition.getX(), belowDoorPosition.getY(), belowDoorPosition.getZ());
+ ChunkUtils.updateBlock(session, belowDoorBlockState, belowDoorPosition);
+ }
+ }
+}
diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/FlowerPotBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/level/block/type/FlowerPotBlock.java
similarity index 60%
rename from core/src/main/java/org/geysermc/geyser/translator/level/block/entity/FlowerPotBlockEntityTranslator.java
rename to core/src/main/java/org/geysermc/geyser/level/block/type/FlowerPotBlock.java
index 074fff6ef..5107616af 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/FlowerPotBlockEntityTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/level/block/type/FlowerPotBlock.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
+ * Copyright (c) 2024 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
@@ -23,64 +23,36 @@
* @link https://github.com/GeyserMC/Geyser
*/
-package org.geysermc.geyser.translator.level.block.entity;
+package org.geysermc.geyser.level.block.type;
import org.cloudburstmc.math.vector.Vector3i;
import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.nbt.NbtMapBuilder;
import org.cloudburstmc.protocol.bedrock.packet.UpdateBlockPacket;
-import org.geysermc.geyser.level.block.BlockStateValues;
+import org.geysermc.geyser.level.block.Blocks;
import org.geysermc.geyser.session.GeyserSession;
+import org.geysermc.geyser.translator.level.block.entity.BedrockChunkWantsBlockEntityTag;
+import org.geysermc.geyser.translator.level.block.entity.BlockEntityTranslator;
import org.geysermc.geyser.util.BlockEntityUtils;
+import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack;
-public class FlowerPotBlockEntityTranslator implements BedrockOnlyBlockEntity {
- /**
- * @param blockState the Java block state of a potential flower pot block
- * @return true if the block is a flower pot
- */
- public static boolean isFlowerBlock(int blockState) {
- return BlockStateValues.getFlowerPotValues().containsKey(blockState);
- }
+public class FlowerPotBlock extends Block implements BedrockChunkWantsBlockEntityTag {
+ private final Block flower;
- /**
- * Get the Nukkit CompoundTag of the flower pot.
- *
- * @param blockState Java block state of flower pot.
- * @param position Bedrock position of flower pot.
- * @return Bedrock tag of flower pot.
- */
- public static NbtMap getTag(GeyserSession session, int blockState, Vector3i position) {
- NbtMapBuilder tagBuilder = NbtMap.builder()
- .putInt("x", position.getX())
- .putInt("y", position.getY())
- .putInt("z", position.getZ())
- .putByte("isMovable", (byte) 1)
- .putString("id", "FlowerPot");
- // Get the Java name of the plant inside. e.g. minecraft:oak_sapling
- String name = BlockStateValues.getFlowerPotValues().get(blockState);
- if (name != null) {
- // Get the Bedrock CompoundTag of the block.
- // This is where we need to store the *Java* name because Bedrock has six minecraft:sapling blocks with different block states.
- NbtMap plant = session.getBlockMappings().getFlowerPotBlocks().get(name);
- if (plant != null) {
- tagBuilder.put("PlantBlock", plant.toBuilder().build());
- }
- }
- return tagBuilder.build();
+ public FlowerPotBlock(String javaIdentifier, Block flower, Builder builder) {
+ super(javaIdentifier, builder);
+ this.flower = flower;
}
@Override
- public boolean isBlock(int blockState) {
- return isFlowerBlock(blockState);
- }
+ public void updateBlock(GeyserSession session, BlockState state, Vector3i position) {
+ super.updateBlock(session, state, position);
- @Override
- public void updateBlock(GeyserSession session, int blockState, Vector3i position) {
- NbtMap tag = getTag(session, blockState, position);
+ NbtMap tag = createTag(session, position, state);
BlockEntityUtils.updateBlockEntity(session, tag, position);
UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket();
updateBlockPacket.setDataLayer(0);
- updateBlockPacket.setDefinition(session.getBlockMappings().getBedrockBlock(blockState));
+ updateBlockPacket.setDefinition(session.getBlockMappings().getBedrockBlock(state));
updateBlockPacket.setBlockPosition(position);
updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NEIGHBORS);
updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NETWORK);
@@ -88,4 +60,33 @@ public class FlowerPotBlockEntityTranslator implements BedrockOnlyBlockEntity {
session.sendUpstreamPacket(updateBlockPacket);
BlockEntityUtils.updateBlockEntity(session, tag, position);
}
+
+ @Override
+ public NbtMap createTag(GeyserSession session, Vector3i position, BlockState blockState) {
+ NbtMapBuilder tagBuilder = BlockEntityTranslator.getConstantBedrockTag("FlowerPot", position.getX(), position.getY(), position.getZ())
+ .putByte("isMovable", (byte) 1);
+ // Get the Java name of the plant inside. e.g. minecraft:oak_sapling
+ if (this.flower != Blocks.AIR) {
+ // Get the Bedrock CompoundTag of the block.
+ // This is where we need to store the *Java* name because Bedrock has six minecraft:sapling blocks with different block states.
+ // TODO flattening might make this nicer in the future!
+ NbtMap plant = session.getBlockMappings().getFlowerPotBlocks().get(this.flower);
+ if (plant != null) {
+ tagBuilder.putCompound("PlantBlock", plant.toBuilder().build());
+ }
+ }
+ return tagBuilder.build();
+ }
+
+ @Override
+ public ItemStack pickItem(BlockState state) {
+ if (this.flower != Blocks.AIR) {
+ return new ItemStack(this.flower.asItem().javaId());
+ }
+ return super.pickItem(state);
+ }
+
+ public Block flower() {
+ return flower;
+ }
}
diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/FurnaceBlock.java b/core/src/main/java/org/geysermc/geyser/level/block/type/FurnaceBlock.java
new file mode 100644
index 000000000..25d54ff2d
--- /dev/null
+++ b/core/src/main/java/org/geysermc/geyser/level/block/type/FurnaceBlock.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2024 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.level.block.type;
+
+import org.geysermc.geyser.level.block.property.Properties;
+import org.geysermc.geyser.level.physics.Direction;
+
+public class FurnaceBlock extends Block {
+ public FurnaceBlock(String javaIdentifier, Builder builder) {
+ super(javaIdentifier, builder);
+ }
+
+ @Override
+ protected BlockState setDefaultState(BlockState firstState) {
+ // Both furnace minecart states look north.
+ return firstState.withValue(Properties.HORIZONTAL_FACING, Direction.NORTH);
+ }
+}
diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/HoneyBlock.java b/core/src/main/java/org/geysermc/geyser/level/block/type/HoneyBlock.java
new file mode 100644
index 000000000..642240915
--- /dev/null
+++ b/core/src/main/java/org/geysermc/geyser/level/block/type/HoneyBlock.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2024 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.level.block.type;
+
+public class HoneyBlock extends Block {
+ public HoneyBlock(String javaIdentifier, Builder builder) {
+ super(javaIdentifier, builder);
+ }
+}
diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/LecternBlock.java b/core/src/main/java/org/geysermc/geyser/level/block/type/LecternBlock.java
new file mode 100644
index 000000000..3139bd6de
--- /dev/null
+++ b/core/src/main/java/org/geysermc/geyser/level/block/type/LecternBlock.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2024 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.level.block.type;
+
+import org.cloudburstmc.math.vector.Vector3i;
+import org.cloudburstmc.nbt.NbtMap;
+import org.cloudburstmc.nbt.NbtMapBuilder;
+import org.cloudburstmc.nbt.NbtType;
+import org.geysermc.geyser.level.WorldManager;
+import org.geysermc.geyser.level.block.property.Properties;
+import org.geysermc.geyser.session.GeyserSession;
+import org.geysermc.geyser.translator.level.block.entity.BedrockChunkWantsBlockEntityTag;
+import org.geysermc.geyser.translator.level.block.entity.BlockEntityTranslator;
+import org.geysermc.geyser.util.BlockEntityUtils;
+
+import java.util.Collections;
+
+public class LecternBlock extends Block implements BedrockChunkWantsBlockEntityTag {
+ public LecternBlock(String javaIdentifier, Builder builder) {
+ super(javaIdentifier, builder);
+ }
+
+ @Override
+ public NbtMap createTag(GeyserSession session, Vector3i position, BlockState blockState) {
+ return getBaseLecternTag(position, blockState.getValue(Properties.HAS_BOOK));
+ }
+
+ @Override
+ public void updateBlock(GeyserSession session, BlockState state, Vector3i position) {
+ WorldManager worldManager = session.getGeyser().getWorldManager();
+ boolean currentHasBook = state.getValue(Properties.HAS_BOOK);
+ Boolean previousHasBook = worldManager.blockAt(session, position).getValueNullable(Properties.HAS_BOOK); // Can be null if not a lectern, watch out
+ if (previousHasBook == null || currentHasBook != previousHasBook) {
+ BlockEntityUtils.updateBlockEntity(session, getBaseLecternTag(position, currentHasBook), position);
+ }
+ super.updateBlock(session, state, position);
+ }
+
+ public static NbtMap getBaseLecternTag(Vector3i position, boolean hasBook) {
+ if (hasBook) {
+ return getBaseLecternTag(position, 1)
+ .putCompound("book", NbtMap.builder()
+ .putByte("Count", (byte) 1)
+ .putShort("Damage", (short) 0)
+ .putString("Name", "minecraft:writable_book")
+ .putCompound("tag", NbtMap.builder().putList("pages", NbtType.COMPOUND, Collections.singletonList(
+ NbtMap.builder()
+ .putString("photoname", "")
+ .putString("text", "")
+ .build()
+ )).build())
+ .build())
+ .build();
+ } else {
+ return getBaseLecternTag(position, 0).build();
+ }
+ }
+
+ public static NbtMapBuilder getBaseLecternTag(Vector3i position, int pages) {
+ NbtMapBuilder builder = BlockEntityTranslator.getConstantBedrockTag("Lectern", position);
+ builder.putBoolean("isMovable", true);
+
+ if (pages != 0) {
+ builder.putByte("hasBook", (byte) 1);
+ builder.putInt("totalPages", 1); // we'll override it anyway
+ }
+
+ return builder;
+ }
+}
diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/MovingPistonBlock.java b/core/src/main/java/org/geysermc/geyser/level/block/type/MovingPistonBlock.java
new file mode 100644
index 000000000..e4df8d88b
--- /dev/null
+++ b/core/src/main/java/org/geysermc/geyser/level/block/type/MovingPistonBlock.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2024 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.level.block.type;
+
+import org.cloudburstmc.math.vector.Vector3i;
+import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition;
+import org.geysermc.geyser.session.GeyserSession;
+
+public class MovingPistonBlock extends Block {
+ public MovingPistonBlock(String javaIdentifier, Builder builder) {
+ super(javaIdentifier, builder);
+ }
+
+ @Override
+ protected void sendBlockUpdatePacket(GeyserSession session, BlockState state, BlockDefinition definition, Vector3i position) {
+ // Prevent moving_piston from being placed
+ // It's used for extending piston heads, but it isn't needed on Bedrock and causes pistons to flicker
+ }
+}
diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/PistonBlock.java b/core/src/main/java/org/geysermc/geyser/level/block/type/PistonBlock.java
new file mode 100644
index 000000000..fc54115eb
--- /dev/null
+++ b/core/src/main/java/org/geysermc/geyser/level/block/type/PistonBlock.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2024 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.level.block.type;
+
+import org.cloudburstmc.math.vector.Vector3i;
+import org.cloudburstmc.nbt.NbtMap;
+import org.geysermc.geyser.level.block.Blocks;
+import org.geysermc.geyser.level.block.property.Properties;
+import org.geysermc.geyser.session.GeyserSession;
+import org.geysermc.geyser.translator.level.block.entity.BedrockChunkWantsBlockEntityTag;
+import org.geysermc.geyser.translator.level.block.entity.PistonBlockEntity;
+
+public class PistonBlock extends Block implements BedrockChunkWantsBlockEntityTag {
+ public PistonBlock(String javaIdentifier, Builder builder) {
+ super(javaIdentifier, builder);
+ }
+
+ @Override
+ public NbtMap createTag(GeyserSession session, Vector3i position, BlockState blockState) {
+ boolean extended = blockState.getValue(Properties.EXTENDED);
+ boolean sticky = blockState.is(Blocks.STICKY_PISTON);
+ return PistonBlockEntity.buildStaticPistonTag(position, extended, sticky);
+ }
+}
diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/PistonHeadBlock.java b/core/src/main/java/org/geysermc/geyser/level/block/type/PistonHeadBlock.java
new file mode 100644
index 000000000..8a6b4f41c
--- /dev/null
+++ b/core/src/main/java/org/geysermc/geyser/level/block/type/PistonHeadBlock.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2024 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.level.block.type;
+
+import org.geysermc.geyser.level.block.Blocks;
+import org.geysermc.geyser.level.block.property.Properties;
+import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack;
+
+public class PistonHeadBlock extends Block {
+ public PistonHeadBlock(String javaIdentifier, Builder builder) {
+ super(javaIdentifier, builder);
+ }
+
+ @Override
+ public ItemStack pickItem(BlockState state) {
+ Block block = state.getValue(Properties.PISTON_TYPE).equals("sticky") ? Blocks.STICKY_PISTON : Blocks.PISTON;
+ return new ItemStack(block.asItem().javaId());
+ }
+}
diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/SkullBlock.java b/core/src/main/java/org/geysermc/geyser/level/block/type/SkullBlock.java
new file mode 100644
index 000000000..c4aae46a2
--- /dev/null
+++ b/core/src/main/java/org/geysermc/geyser/level/block/type/SkullBlock.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2024 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.level.block.type;
+
+import com.github.steveice10.mc.auth.data.GameProfile;
+import org.cloudburstmc.math.vector.Vector3i;
+import org.cloudburstmc.nbt.NbtMap;
+import org.cloudburstmc.nbt.NbtMapBuilder;
+import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition;
+import org.geysermc.geyser.inventory.GeyserItemStack;
+import org.geysermc.geyser.session.GeyserSession;
+import org.geysermc.geyser.session.cache.SkullCache;
+import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack;
+import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType;
+import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents;
+
+import java.util.Collections;
+import java.util.UUID;
+
+public class SkullBlock extends Block {
+ private final Type type;
+
+ public SkullBlock(String javaIdentifier, Type type, Builder builder) {
+ super(javaIdentifier, builder);
+ this.type = type;
+ }
+
+ @Override
+ protected void sendBlockUpdatePacket(GeyserSession session, BlockState state, BlockDefinition definition, Vector3i position) {
+ if (this.type == Type.PLAYER) {
+ // The changed block was a player skull so check if a custom block was defined for this skull
+ SkullCache.Skull skull = session.getSkullCache().updateSkull(position, state);
+ if (skull != null && skull.getBlockDefinition() != null) {
+ definition = skull.getBlockDefinition();
+ }
+ }
+ super.sendBlockUpdatePacket(session, state, definition, position);
+ }
+
+ @Override
+ protected void checkForEmptySkull(GeyserSession session, BlockState state, Vector3i position) {
+ // It's not an empty skull.
+ }
+
+ public ItemStack pickItem(GeyserSession session, BlockState state, Vector3i position) {
+ SkullCache.Skull skull = session.getSkullCache().getSkulls().get(position);
+ if (skull == null) {
+ return new ItemStack(pickItem(state).getId());
+ }
+
+ GeyserItemStack itemStack = GeyserItemStack.of(pickItem(state).getId(), 1);
+ // This is a universal block entity behavior, but hardcode how it works for now.
+ NbtMapBuilder builder = NbtMap.builder()
+ .putString("id", "minecraft:skull")
+ .putInt("x", position.getX())
+ .putInt("y", position.getY())
+ .putInt("z", position.getZ());
+ DataComponents components = itemStack.getOrCreateComponents();
+ components.put(DataComponentType.BLOCK_ENTITY_DATA, builder.build());
+
+ UUID uuid = skull.getUuid();
+ String texturesProperty = skull.getTexturesProperty();
+ GameProfile profile = new GameProfile(uuid, null);
+ if (texturesProperty != null) {
+ profile.setProperties(Collections.singletonList(new GameProfile.Property("textures", texturesProperty)));
+ }
+ components.put(DataComponentType.PROFILE, profile);
+ return itemStack.getItemStack();
+ }
+
+ public Type skullType() {
+ return type;
+ }
+
+ /**
+ * Enum order matches Java.
+ */
+ public enum Type {
+ SKELETON(0),
+ WITHER_SKELETON(1),
+ PLAYER(3),
+ ZOMBIE(2),
+ CREEPER(4),
+ PIGLIN(6),
+ DRAGON(5);
+
+ private final int bedrockId;
+
+ Type(int bedrockId) {
+ this.bedrockId = bedrockId;
+ }
+
+ public int bedrockId() {
+ return bedrockId;
+ }
+ }
+}
diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/SpawnerBlock.java b/core/src/main/java/org/geysermc/geyser/level/block/type/SpawnerBlock.java
new file mode 100644
index 000000000..968499d11
--- /dev/null
+++ b/core/src/main/java/org/geysermc/geyser/level/block/type/SpawnerBlock.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2024 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.level.block.type;
+
+public class SpawnerBlock extends Block {
+ public SpawnerBlock(String javaIdentifier, Builder builder) {
+ super(javaIdentifier, builder);
+ }
+}
diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/TrapDoorBlock.java b/core/src/main/java/org/geysermc/geyser/level/block/type/TrapDoorBlock.java
new file mode 100644
index 000000000..a94414ac2
--- /dev/null
+++ b/core/src/main/java/org/geysermc/geyser/level/block/type/TrapDoorBlock.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2024 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.level.block.type;
+
+public class TrapDoorBlock extends Block {
+ public TrapDoorBlock(String javaIdentifier, Builder builder) {
+ super(javaIdentifier, builder);
+ }
+}
diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/WallSkullBlock.java b/core/src/main/java/org/geysermc/geyser/level/block/type/WallSkullBlock.java
new file mode 100644
index 000000000..e8fedcc76
--- /dev/null
+++ b/core/src/main/java/org/geysermc/geyser/level/block/type/WallSkullBlock.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2024 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.level.block.type;
+
+import org.geysermc.geyser.level.block.property.Properties;
+import org.geysermc.geyser.level.physics.Direction;
+
+public class WallSkullBlock extends SkullBlock {
+ public WallSkullBlock(String javaIdentifier, Type type, Builder builder) {
+ super(javaIdentifier, type, builder);
+ }
+
+ public static int getDegrees(BlockState state) {
+ return getDegrees(state.getValue(Properties.HORIZONTAL_FACING));
+ }
+
+ public static int getDegrees(Direction direction) {
+ return switch (direction) {
+ case NORTH -> 180;
+ case WEST -> 90;
+ case EAST -> 270;
+ case SOUTH -> 0;
+ default -> throw new IllegalStateException();
+ };
+ }
+}
diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/WaterBlock.java b/core/src/main/java/org/geysermc/geyser/level/block/type/WaterBlock.java
new file mode 100644
index 000000000..9d2d23116
--- /dev/null
+++ b/core/src/main/java/org/geysermc/geyser/level/block/type/WaterBlock.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2024 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.level.block.type;
+
+public class WaterBlock extends Block {
+ public WaterBlock(String javaIdentifier, Builder builder) {
+ super(javaIdentifier, builder);
+ }
+}
diff --git a/core/src/main/java/org/geysermc/geyser/level/physics/CollisionManager.java b/core/src/main/java/org/geysermc/geyser/level/physics/CollisionManager.java
index ce89689eb..2be4e7a38 100644
--- a/core/src/main/java/org/geysermc/geyser/level/physics/CollisionManager.java
+++ b/core/src/main/java/org/geysermc/geyser/level/physics/CollisionManager.java
@@ -39,6 +39,9 @@ import org.geysermc.geyser.entity.EntityDefinitions;
import org.geysermc.geyser.entity.type.Entity;
import org.geysermc.geyser.entity.type.player.PlayerEntity;
import org.geysermc.geyser.level.block.BlockStateValues;
+import org.geysermc.geyser.level.block.Blocks;
+import org.geysermc.geyser.level.block.property.Properties;
+import org.geysermc.geyser.level.block.type.BlockState;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.session.cache.PistonCache;
import org.geysermc.geyser.translator.collision.BlockCollision;
@@ -405,7 +408,8 @@ public class CollisionManager {
* @return if the player is currently in a water block
*/
public boolean isPlayerInWater() {
- return session.getGeyser().getWorldManager().getBlockAt(session, session.getPlayerEntity().getPosition().toInt()) == BlockStateValues.JAVA_WATER_ID;
+ BlockState state = session.getGeyser().getWorldManager().blockAt(session, session.getPlayerEntity().getPosition().toInt());
+ return state.is(Blocks.WATER) && state.getValue(Properties.LEVEL) == 0;
}
public boolean isWaterInEyes() {
diff --git a/core/src/main/java/org/geysermc/geyser/network/CodecProcessor.java b/core/src/main/java/org/geysermc/geyser/network/CodecProcessor.java
index 6bd767fb7..e7cf81d47 100644
--- a/core/src/main/java/org/geysermc/geyser/network/CodecProcessor.java
+++ b/core/src/main/java/org/geysermc/geyser/network/CodecProcessor.java
@@ -224,7 +224,7 @@ class CodecProcessor {
@SuppressWarnings("unchecked")
static BedrockCodec processCodec(BedrockCodec codec) {
- return codec.toBuilder()
+ BedrockCodec.Builder codecBuilder = codec.toBuilder()
// Illegal unused serverbound EDU packets
.updateSerializer(PhotoTransferPacket.class, ILLEGAL_SERIALIZER)
.updateSerializer(LabTablePacket.class, ILLEGAL_SERIALIZER)
@@ -232,10 +232,11 @@ class CodecProcessor {
.updateSerializer(CreatePhotoPacket.class, ILLEGAL_SERIALIZER)
.updateSerializer(NpcRequestPacket.class, ILLEGAL_SERIALIZER)
.updateSerializer(PhotoInfoRequestPacket.class, ILLEGAL_SERIALIZER)
- // Illegal unused serverbound packets for featured servers
- .updateSerializer(PurchaseReceiptPacket.class, ILLEGAL_SERIALIZER)
+ // Unused serverbound packets for featured servers, which is for some reason still occasionally sent
+ .updateSerializer(PurchaseReceiptPacket.class, IGNORED_SERIALIZER)
// Illegal unused serverbound packets that are deprecated
.updateSerializer(ClientCheatAbilityPacket.class, ILLEGAL_SERIALIZER)
+ .updateSerializer(CraftingEventPacket.class, ILLEGAL_SERIALIZER)
// Illegal unusued serverbound packets that relate to unused features
.updateSerializer(PlayerAuthInputPacket.class, ILLEGAL_SERIALIZER)
.updateSerializer(ClientCacheBlobStatusPacket.class, ILLEGAL_SERIALIZER)
@@ -243,7 +244,6 @@ class CodecProcessor {
.updateSerializer(SubChunkRequestPacket.class, ILLEGAL_SERIALIZER)
.updateSerializer(GameTestRequestPacket.class, ILLEGAL_SERIALIZER)
// Ignored serverbound packets
- .updateSerializer(CraftingEventPacket.class, IGNORED_SERIALIZER) // Make illegal when 1.20.40 is removed
.updateSerializer(ClientToServerHandshakePacket.class, IGNORED_SERIALIZER)
.updateSerializer(EntityFallPacket.class, IGNORED_SERIALIZER)
.updateSerializer(MapCreateLockedCopyPacket.class, IGNORED_SERIALIZER)
@@ -260,22 +260,25 @@ class CodecProcessor {
.updateSerializer(PlayerHotbarPacket.class, PLAYER_HOTBAR_SERIALIZER)
.updateSerializer(PlayerSkinPacket.class, PLAYER_SKIN_SERIALIZER)
.updateSerializer(SetEntityDataPacket.class, SET_ENTITY_DATA_SERIALIZER)
- .updateSerializer(SetEntityMotionPacket.class, codec.getProtocolVersion() < 662 ?
- SET_ENTITY_MOTION_SERIALIZER_V291 :
- SET_ENTITY_MOTION_SERIALIZER_V662)
+ .updateSerializer(SetEntityMotionPacket.class, SET_ENTITY_MOTION_SERIALIZER_V662)
.updateSerializer(SetEntityLinkPacket.class, SET_ENTITY_LINK_SERIALIZER)
// Valid serverbound packets where reading of some fields can be skipped
.updateSerializer(MobEquipmentPacket.class, MOB_EQUIPMENT_SERIALIZER)
- // // Illegal bidirectional packets
+ // Illegal bidirectional packets
.updateSerializer(DebugInfoPacket.class, ILLEGAL_SERIALIZER)
.updateSerializer(EditorNetworkPacket.class, ILLEGAL_SERIALIZER)
.updateSerializer(ScriptMessagePacket.class, ILLEGAL_SERIALIZER)
- // // Ignored bidirectional packets
+ // Ignored bidirectional packets
.updateSerializer(ClientCacheStatusPacket.class, IGNORED_SERIALIZER)
.updateSerializer(SimpleEventPacket.class, IGNORED_SERIALIZER)
- .updateSerializer(TickSyncPacket.class, IGNORED_SERIALIZER)
- .updateSerializer(MultiplayerSettingsPacket.class, IGNORED_SERIALIZER)
- .build();
+ .updateSerializer(MultiplayerSettingsPacket.class, IGNORED_SERIALIZER);
+
+ if (codec.getProtocolVersion() < 685) {
+ // Ignored bidirectional packets
+ codecBuilder.updateSerializer(TickSyncPacket.class, IGNORED_SERIALIZER);
+ }
+
+ return codecBuilder.build();
}
/**
diff --git a/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java b/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java
index f9292671f..de995301a 100644
--- a/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java
+++ b/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java
@@ -27,11 +27,8 @@ package org.geysermc.geyser.network;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.cloudburstmc.protocol.bedrock.codec.BedrockCodec;
-import org.cloudburstmc.protocol.bedrock.codec.v622.Bedrock_v622;
-import org.cloudburstmc.protocol.bedrock.codec.v630.Bedrock_v630;
-import org.cloudburstmc.protocol.bedrock.codec.v649.Bedrock_v649;
-import org.cloudburstmc.protocol.bedrock.codec.v662.Bedrock_v662;
import org.cloudburstmc.protocol.bedrock.codec.v671.Bedrock_v671;
+import org.cloudburstmc.protocol.bedrock.codec.v685.Bedrock_v685;
import org.cloudburstmc.protocol.bedrock.netty.codec.packet.BedrockPacketCodec;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.mcprotocollib.protocol.codec.MinecraftCodec;
@@ -50,8 +47,8 @@ public final class GameProtocol {
* Default Bedrock codec that should act as a fallback. Should represent the latest available
* release of the game that Geyser supports.
*/
- public static final BedrockCodec DEFAULT_BEDROCK_CODEC = CodecProcessor.processCodec(Bedrock_v671.CODEC.toBuilder()
- .minecraftVersion("1.20.81")
+ public static final BedrockCodec DEFAULT_BEDROCK_CODEC = CodecProcessor.processCodec(Bedrock_v685.CODEC.toBuilder()
+ .minecraftVersion("1.21.1")
.build());
/**
@@ -66,20 +63,11 @@ public final class GameProtocol {
private static final PacketCodec DEFAULT_JAVA_CODEC = MinecraftCodec.CODEC;
static {
- SUPPORTED_BEDROCK_CODECS.add(CodecProcessor.processCodec(Bedrock_v622.CODEC.toBuilder()
- .minecraftVersion("1.20.40/1.20.41")
- .build()));
- SUPPORTED_BEDROCK_CODECS.add(CodecProcessor.processCodec(Bedrock_v630.CODEC.toBuilder()
- .minecraftVersion("1.20.50/1.20.51")
- .build()));
- SUPPORTED_BEDROCK_CODECS.add(CodecProcessor.processCodec(Bedrock_v649.CODEC.toBuilder()
- .minecraftVersion("1.20.60/1.20.62")
- .build()));
- SUPPORTED_BEDROCK_CODECS.add(CodecProcessor.processCodec(Bedrock_v662.CODEC.toBuilder()
- .minecraftVersion("1.20.70/1.20.73")
+ SUPPORTED_BEDROCK_CODECS.add(CodecProcessor.processCodec(Bedrock_v671.CODEC.toBuilder()
+ .minecraftVersion("1.20.80/1.20.81")
.build()));
SUPPORTED_BEDROCK_CODECS.add(CodecProcessor.processCodec(DEFAULT_BEDROCK_CODEC.toBuilder()
- .minecraftVersion("1.20.80/1.20.81")
+ .minecraftVersion("1.21.0/1.20.1")
.build()));
}
@@ -99,16 +87,8 @@ public final class GameProtocol {
/* Bedrock convenience methods to gatekeep features and easily remove the check on version removal */
- public static boolean isPre1_20_50(GeyserSession session) {
- return session.getUpstream().getProtocolVersion() < Bedrock_v630.CODEC.getProtocolVersion();
- }
-
- public static boolean isPre1_20_70(GeyserSession session) {
- return session.getUpstream().getProtocolVersion() < Bedrock_v662.CODEC.getProtocolVersion();
- }
-
- public static boolean is1_20_60orHigher(int protocolVersion) {
- return protocolVersion >= Bedrock_v649.CODEC.getProtocolVersion();
+ public static boolean isPre1_21_0(GeyserSession session) {
+ return session.getUpstream().getProtocolVersion() < Bedrock_v685.CODEC.getProtocolVersion();
}
/**
@@ -126,7 +106,7 @@ public final class GameProtocol {
* @return the supported Minecraft: Java Edition version names
*/
public static List getJavaVersions() {
- return List.of("1.20.5", DEFAULT_JAVA_CODEC.getMinecraftVersion());
+ return List.of(DEFAULT_JAVA_CODEC.getMinecraftVersion());
}
/**
diff --git a/core/src/main/java/org/geysermc/geyser/network/GeyserServerInitializer.java b/core/src/main/java/org/geysermc/geyser/network/GeyserServerInitializer.java
index 662e2f4c7..5c83702ae 100644
--- a/core/src/main/java/org/geysermc/geyser/network/GeyserServerInitializer.java
+++ b/core/src/main/java/org/geysermc/geyser/network/GeyserServerInitializer.java
@@ -25,11 +25,8 @@
package org.geysermc.geyser.network;
-import io.netty.buffer.ByteBuf;
import io.netty.channel.Channel;
-import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.DefaultEventLoopGroup;
-import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.util.concurrent.DefaultThreadFactory;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.cloudburstmc.protocol.bedrock.BedrockPeer;
@@ -37,7 +34,6 @@ import org.cloudburstmc.protocol.bedrock.BedrockServerSession;
import org.cloudburstmc.protocol.bedrock.netty.codec.packet.BedrockPacketCodec;
import org.cloudburstmc.protocol.bedrock.netty.initializer.BedrockServerInitializer;
import org.geysermc.geyser.GeyserImpl;
-import org.geysermc.geyser.api.event.bedrock.SessionInitializeEvent;
import org.geysermc.geyser.session.GeyserSession;
import java.net.InetSocketAddress;
@@ -72,7 +68,6 @@ public class GeyserServerInitializer extends BedrockServerInitializer {
channel.pipeline().addAfter(BedrockPacketCodec.NAME, InvalidPacketHandler.NAME, new InvalidPacketHandler(session));
bedrockServerSession.setPacketHandler(new UpstreamPacketHandler(this.geyser, session));
- this.geyser.eventBus().fire(new SessionInitializeEvent(session));
} catch (Throwable e) {
// Error must be caught or it will be swallowed
this.geyser.getLogger().error("Error occurred while initializing player!", e);
diff --git a/core/src/main/java/org/geysermc/geyser/network/InvalidPacketHandler.java b/core/src/main/java/org/geysermc/geyser/network/InvalidPacketHandler.java
index 3e836711b..1b653891e 100644
--- a/core/src/main/java/org/geysermc/geyser/network/InvalidPacketHandler.java
+++ b/core/src/main/java/org/geysermc/geyser/network/InvalidPacketHandler.java
@@ -47,7 +47,9 @@ public class InvalidPacketHandler extends ChannelInboundHandlerAdapter {
if (!(rootCause instanceof IllegalArgumentException)) {
- super.exceptionCaught(ctx, cause);
+ // Kick users that cause exceptions
+ session.getGeyser().getLogger().warning("Exception caught in session of" + session.bedrockUsername() + ": " + rootCause.getMessage());
+ session.disconnect("An internal error occurred!");
return;
}
diff --git a/core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java b/core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java
index 59485b2cd..c7aabb806 100644
--- a/core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java
+++ b/core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java
@@ -54,6 +54,7 @@ import org.cloudburstmc.protocol.common.PacketSignal;
import org.cloudburstmc.protocol.common.util.Zlib;
import org.geysermc.geyser.Constants;
import org.geysermc.geyser.GeyserImpl;
+import org.geysermc.geyser.api.event.bedrock.SessionInitializeEvent;
import org.geysermc.geyser.api.network.AuthType;
import org.geysermc.geyser.api.pack.PackCodec;
import org.geysermc.geyser.api.pack.ResourcePack;
@@ -131,6 +132,8 @@ public class UpstreamPacketHandler extends LoggingPacketHandler {
}
session.getUpstream().getSession().setCodec(packetCodec);
+ // FIXME temporary until 1.20.80 is dropped
+ session.getPlayerEntity().resetAir();
return true;
}
@@ -188,6 +191,9 @@ public class UpstreamPacketHandler extends LoggingPacketHandler {
return PacketSignal.HANDLED;
}
+ // Fire SessionInitializeEvent here as we now know the client data
+ geyser.eventBus().fire(new SessionInitializeEvent(session));
+
PlayStatusPacket playStatus = new PlayStatusPacket();
playStatus.setStatus(PlayStatusPacket.Status.LOGIN_SUCCESS);
session.sendUpstreamPacket(playStatus);
diff --git a/core/src/main/java/org/geysermc/geyser/pack/SkullResourcePackManager.java b/core/src/main/java/org/geysermc/geyser/pack/SkullResourcePackManager.java
index f0faa4244..59651d139 100644
--- a/core/src/main/java/org/geysermc/geyser/pack/SkullResourcePackManager.java
+++ b/core/src/main/java/org/geysermc/geyser/pack/SkullResourcePackManager.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
+ * Copyright (c) 2019-2024 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
@@ -118,7 +118,7 @@ public class SkullResourcePackManager {
return;
}
- BufferedImage image = SkinProvider.requestImage(skinUrl, null);
+ BufferedImage image = SkinProvider.requestImage(skinUrl, false);
// Resize skins to 48x16 to save on space and memory
BufferedImage skullTexture = new BufferedImage(48, 16, image.getType());
// Reorder skin parts to fit into the space
diff --git a/core/src/main/java/org/geysermc/geyser/ping/GeyserLegacyPingPassthrough.java b/core/src/main/java/org/geysermc/geyser/ping/GeyserLegacyPingPassthrough.java
index 320334ee5..27b405348 100644
--- a/core/src/main/java/org/geysermc/geyser/ping/GeyserLegacyPingPassthrough.java
+++ b/core/src/main/java/org/geysermc/geyser/ping/GeyserLegacyPingPassthrough.java
@@ -35,10 +35,7 @@ import org.cloudburstmc.nbt.util.VarInts;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.network.GameProtocol;
-import java.io.ByteArrayOutputStream;
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.IOException;
+import java.io.*;
import java.net.*;
import java.util.concurrent.TimeUnit;
@@ -139,6 +136,9 @@ public class GeyserLegacyPingPassthrough implements IGeyserPingPassthrough, Runn
this.geyser.getLogger().debug("Connection timeout for ping passthrough.");
} catch (JsonParseException | JsonMappingException ex) {
this.geyser.getLogger().error("Failed to parse json when pinging server!", ex);
+ } catch (EOFException e) {
+ this.pingInfo = null;
+ this.geyser.getLogger().warning("Failed to ping the remote Java server! Is it online and configured in Geyser's config?");
} catch (UnknownHostException ex) {
// Don't reset pingInfo, as we want to keep the last known value
this.geyser.getLogger().warning("Unable to resolve remote host! Is the remote server down or invalid?");
diff --git a/core/src/main/java/org/geysermc/geyser/registry/BlockRegistries.java b/core/src/main/java/org/geysermc/geyser/registry/BlockRegistries.java
index aa9d6fc36..2f15094ef 100644
--- a/core/src/main/java/org/geysermc/geyser/registry/BlockRegistries.java
+++ b/core/src/main/java/org/geysermc/geyser/registry/BlockRegistries.java
@@ -34,18 +34,20 @@ import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import org.geysermc.geyser.api.block.custom.CustomBlockData;
import org.geysermc.geyser.api.block.custom.CustomBlockState;
import org.geysermc.geyser.api.block.custom.nonvanilla.JavaBlockState;
+import org.geysermc.geyser.level.block.Blocks;
+import org.geysermc.geyser.level.block.type.Block;
+import org.geysermc.geyser.level.block.type.BlockState;
import org.geysermc.geyser.registry.loader.CollisionRegistryLoader;
import org.geysermc.geyser.registry.loader.RegistryLoaders;
import org.geysermc.geyser.registry.populator.BlockRegistryPopulator;
import org.geysermc.geyser.registry.populator.CustomBlockRegistryPopulator;
import org.geysermc.geyser.registry.populator.CustomSkullRegistryPopulator;
-import org.geysermc.geyser.registry.type.BlockMapping;
import org.geysermc.geyser.registry.type.BlockMappings;
import org.geysermc.geyser.registry.type.CustomSkull;
import org.geysermc.geyser.translator.collision.BlockCollision;
+import java.util.ArrayList;
import java.util.BitSet;
-
import java.util.Set;
/**
@@ -59,34 +61,32 @@ public class BlockRegistries {
public static final VersionedRegistry BLOCKS = VersionedRegistry.create(RegistryLoaders.empty(Int2ObjectOpenHashMap::new));
/**
- * A mapped registry which stores Java to Bedrock block identifiers.
+ * A registry which stores Java IDs to Java {@link BlockState}s, each with their specific state differences and a link
+ * to the overarching block.
*/
- public static final SimpleMappedRegistry JAVA_TO_BEDROCK_IDENTIFIERS = SimpleMappedRegistry.create(RegistryLoaders.empty(Object2ObjectOpenHashMap::new));
-
- /**
- * A registry which stores Java IDs to {@link BlockMapping}, containing miscellaneous information about
- * blocks and their behavior in many cases.
- */
- public static final ArrayRegistry JAVA_BLOCKS = ArrayRegistry.create(RegistryLoaders.uninitialized());
+ public static final ListRegistry BLOCK_STATES = ListRegistry.create(RegistryLoaders.empty(ArrayList::new));
/**
* A mapped registry containing which holds block IDs to its {@link BlockCollision}.
*/
- public static final IntMappedRegistry COLLISIONS;
+ public static final ListRegistry COLLISIONS;
+
+ /**
+ * A registry which stores Java IDs to {@link Block}, containing miscellaneous information about
+ * blocks and their behavior in many cases.
+ */
+ public static final ListRegistry JAVA_BLOCKS = ListRegistry.create(RegistryLoaders.empty(ArrayList::new));
/**
* A mapped registry containing the Java identifiers to IDs.
*/
public static final MappedRegistry> JAVA_IDENTIFIER_TO_ID = MappedRegistry.create(RegistryLoaders.empty(Object2IntOpenHashMap::new));
- /**
- * A registry which stores unique Java IDs to its clean identifier
- * This is used in the statistics form.
- */
- public static final ArrayRegistry CLEAN_JAVA_IDENTIFIERS = ArrayRegistry.create(RegistryLoaders.uninitialized());
-
/**
* A registry containing all the waterlogged blockstates.
+ * Properties.WATERLOGGED should not be relied on for two reasons:
+ * - Custom blocks
+ * - Seagrass, kelp, and bubble columns are assumed waterlogged and don't have a waterlogged property
*/
public static final SimpleRegistry WATERLOGGED = SimpleRegistry.create(RegistryLoaders.empty(BitSet::new));
@@ -131,12 +131,13 @@ public class BlockRegistries {
public static final SimpleMappedRegistry CUSTOM_SKULLS = SimpleMappedRegistry.create(RegistryLoaders.empty(Object2ObjectOpenHashMap::new));
static {
+ Blocks.VAULT.javaId(); // FIXME
CustomSkullRegistryPopulator.populate();
BlockRegistryPopulator.populate(BlockRegistryPopulator.Stage.PRE_INIT);
CustomBlockRegistryPopulator.populate(CustomBlockRegistryPopulator.Stage.DEFINITION);
CustomBlockRegistryPopulator.populate(CustomBlockRegistryPopulator.Stage.NON_VANILLA_REGISTRATION);
BlockRegistryPopulator.populate(BlockRegistryPopulator.Stage.INIT_JAVA);
- COLLISIONS = IntMappedRegistry.create(Pair.of("org.geysermc.geyser.translator.collision.CollisionRemapper", "mappings/collision.json"), CollisionRegistryLoader::new);
+ COLLISIONS = ListRegistry.create(Pair.of("org.geysermc.geyser.translator.collision.CollisionRemapper", "mappings/collisions.nbt"), CollisionRegistryLoader::new);
CustomBlockRegistryPopulator.populate(CustomBlockRegistryPopulator.Stage.VANILLA_REGISTRATION);
CustomBlockRegistryPopulator.populate(CustomBlockRegistryPopulator.Stage.CUSTOM_REGISTRATION);
BlockRegistryPopulator.populate(BlockRegistryPopulator.Stage.INIT_BEDROCK);
diff --git a/core/src/main/java/org/geysermc/geyser/registry/IntMappedRegistry.java b/core/src/main/java/org/geysermc/geyser/registry/IntMappedRegistry.java
deleted file mode 100644
index 981ed0f8c..000000000
--- a/core/src/main/java/org/geysermc/geyser/registry/IntMappedRegistry.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * 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 it.unimi.dsi.fastutil.ints.Int2ObjectMap;
-import org.checkerframework.checker.nullness.qual.Nullable;
-import org.geysermc.geyser.registry.loader.RegistryLoader;
-
-import java.util.function.Supplier;
-
-/**
- * A mapped registry with an integer as the key. This class is designed to minimize the need for boxing/unboxing keys.
- *
- * @param the value
- */
-public class IntMappedRegistry extends AbstractMappedRegistry> {
- protected IntMappedRegistry(I input, RegistryLoader> registryLoader) {
- super(input, registryLoader);
- }
-
- /**
- * Returns the value registered by the given integer.
- *
- * @param i the integer
- * @return the value registered by the given integer.
- */
- public V get(int i) {
- return this.mappings.get(i);
- }
-
- @Nullable
- @Override
- @Deprecated
- public V get(Integer key) {
- return super.get(key);
- }
-
- /**
- * Returns the value registered by the given key or the default value
- * specified if null.
- *
- * @param i the key
- * @param defaultValue the default value
- * @return the value registered by the given key or the default value
- * specified if null.
- */
- public V getOrDefault(int i, V defaultValue) {
- return this.mappings.getOrDefault(i, defaultValue);
- }
-
- @Override
- @Deprecated
- public V getOrDefault(Integer key, V defaultValue) {
- return super.getOrDefault(key, defaultValue);
- }
-
- /**
- * Registers a new value into this registry with the given key.
- *
- * @param i the key
- * @param value the value
- * @return a new value into this registry with the given key.
- */
- public V register(int i, V value) {
- return this.mappings.put(i, value);
- }
-
- @Override
- @Deprecated
- public V register(Integer key, V value) {
- return super.register(key, value);
- }
-
- /**
- * Creates a new integer mapped registry with the given {@link RegistryLoader}. The
- * input type is not specified here, meaning the loader return type is either
- * predefined, or the registry is populated at a later point.
- *
- * @param registryLoader the registry loader
- * @param the input
- * @param the map value
- * @return a new registry with the given RegistryLoader
- */
- public static IntMappedRegistry create(RegistryLoader> registryLoader) {
- return new IntMappedRegistry<>(null, registryLoader);
- }
-
- /**
- * Creates a new integer mapped registry with the given {@link RegistryLoader} and input.
- *
- * @param registryLoader the registry loader
- * @param the input
- * @param the map value
- * @return a new registry with the given RegistryLoader supplier
- */
- public static IntMappedRegistry create(I input, Supplier>> registryLoader) {
- return new IntMappedRegistry<>(input, registryLoader.get());
- }
-}
diff --git a/core/src/main/java/org/geysermc/geyser/registry/ListRegistry.java b/core/src/main/java/org/geysermc/geyser/registry/ListRegistry.java
new file mode 100644
index 000000000..2070d67ae
--- /dev/null
+++ b/core/src/main/java/org/geysermc/geyser/registry/ListRegistry.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2024 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.checkerframework.checker.nullness.qual.Nullable;
+import org.geysermc.geyser.registry.loader.RegistryLoader;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.function.Supplier;
+
+public class ListRegistry extends Registry> {
+ private boolean frozen = false;
+
+ /**
+ * Creates a new instance of this class with the given input and
+ * {@link RegistryLoader}. The input specified is what the registry
+ * loader needs to take in.
+ *
+ * @param input the input
+ * @param registryLoader the registry loader
+ */
+ protected ListRegistry(I input, RegistryLoader> registryLoader) {
+ super(input, registryLoader);
+ }
+
+ /**
+ * Returns the value registered by the given index.
+ *
+ * @param index the index
+ * @return the value registered by the given index.
+ */
+ @Nullable
+ public M get(int index) {
+ if (index >= this.mappings.size()) {
+ return null;
+ }
+
+ return this.mappings.get(index);
+ }
+
+ /**
+ * Returns the value registered by the given index or the default value
+ * specified if null.
+ *
+ * @param index the index
+ * @param defaultValue the default value
+ * @return the value registered by the given key or the default value
+ * specified if null.
+ */
+ public M getOrDefault(int index, M defaultValue) {
+ M value = this.get(index);
+ if (value == null) {
+ return defaultValue;
+ }
+
+ return value;
+ }
+
+ /**
+ * Registers a new value into this registry with the given index.
+ *
+ * @param index the index
+ * @param value the value
+ * @return a new value into this registry with the given index.
+ */
+ public M register(int index, M value) {
+ if (this.frozen) {
+ throw new IllegalStateException("Registry should not be modified after frozen!");
+ }
+ return this.mappings.set(index, value);
+ }
+
+ /**
+ * Registers a new value into this registry with the given index, even if this value would normally be outside
+ * the range of a list.
+ *
+ * @param index the index
+ * @param value the value
+ * @param defaultValue the default value to fill empty spaces in the registry with.
+ * @return a new value into this registry with the given index.
+ */
+ public M registerWithAnyIndex(int index, M value, M defaultValue) {
+ if (this.frozen) {
+ throw new IllegalStateException("Registry should not be modified after frozen!");
+ }
+ if (this.mappings.size() <= index) {
+ this.mappings.addAll(Collections.nCopies(index - this.mappings.size() + 1, defaultValue));
+ }
+ return this.mappings.set(index, value);
+ }
+
+ /**
+ * Mark this registry as unsuitable for new additions. The backing list will then be optimized for storage.
+ */
+ public void freeze() {
+ if (!this.frozen) {
+ this.frozen = true;
+ if (this.mappings instanceof ArrayList arrayList) {
+ arrayList.trimToSize();
+ }
+ }
+ }
+
+ /**
+ * Creates a new array registry with the given {@link RegistryLoader}. The
+ * input type is not specified here, meaning the loader return type is either
+ * predefined, or the registry is populated at a later point.
+ *
+ * @param registryLoader the registry loader
+ * @param the input type
+ * @param the returned mappings type
+ * @return a new registry with the given RegistryLoader supplier
+ */
+ public static ListRegistry create(RegistryLoader> registryLoader) {
+ return new ListRegistry<>(null, registryLoader);
+ }
+
+ /**
+ * Creates a new integer mapped registry with the given {@link RegistryLoader} and input.
+ *
+ * @param registryLoader the registry loader
+ * @param the input
+ * @param the type value
+ * @return a new registry with the given RegistryLoader supplier
+ */
+ public static ListRegistry create(I input, Supplier>> registryLoader) {
+ return new ListRegistry<>(input, registryLoader.get());
+ }
+}
diff --git a/core/src/main/java/org/geysermc/geyser/registry/Registries.java b/core/src/main/java/org/geysermc/geyser/registry/Registries.java
index 54d013140..30d3c0763 100644
--- a/core/src/main/java/org/geysermc/geyser/registry/Registries.java
+++ b/core/src/main/java/org/geysermc/geyser/registry/Registries.java
@@ -25,33 +25,23 @@
package org.geysermc.geyser.registry;
-import org.geysermc.mcprotocollib.protocol.data.game.entity.type.EntityType;
-import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType;
-import org.geysermc.mcprotocollib.protocol.data.game.level.event.LevelEvent;
-import org.geysermc.mcprotocollib.protocol.data.game.level.particle.ParticleType;
-import org.geysermc.mcprotocollib.protocol.data.game.recipe.RecipeType;
-import org.geysermc.mcprotocollib.network.packet.Packet;
-import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.nbt.NbtMapBuilder;
import org.cloudburstmc.protocol.bedrock.data.inventory.crafting.PotionMixData;
-import org.cloudburstmc.protocol.bedrock.data.inventory.crafting.recipe.RecipeData;
import org.cloudburstmc.protocol.bedrock.packet.BedrockPacket;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.api.pack.ResourcePack;
import org.geysermc.geyser.entity.EntityDefinition;
-import org.geysermc.geyser.inventory.item.Enchantment.JavaEnchantment;
import org.geysermc.geyser.inventory.recipe.GeyserRecipe;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.registry.loader.*;
import org.geysermc.geyser.registry.populator.ItemRegistryPopulator;
import org.geysermc.geyser.registry.populator.PacketRegistryPopulator;
-import org.geysermc.geyser.registry.populator.RecipeRegistryPopulator;
+import org.geysermc.geyser.registry.loader.RecipeRegistryLoader;
import org.geysermc.geyser.registry.provider.ProviderSupplier;
-import org.geysermc.geyser.registry.type.EnchantmentData;
import org.geysermc.geyser.registry.type.ItemMappings;
import org.geysermc.geyser.registry.type.ParticleMapping;
import org.geysermc.geyser.registry.type.SoundMapping;
@@ -59,6 +49,12 @@ import org.geysermc.geyser.translator.level.block.entity.BlockEntityTranslator;
import org.geysermc.geyser.translator.level.event.LevelEventTranslator;
import org.geysermc.geyser.translator.sound.SoundInteractionTranslator;
import org.geysermc.geyser.translator.sound.SoundTranslator;
+import org.geysermc.mcprotocollib.network.packet.Packet;
+import org.geysermc.mcprotocollib.protocol.data.game.entity.type.EntityType;
+import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType;
+import org.geysermc.mcprotocollib.protocol.data.game.level.event.LevelEvent;
+import org.geysermc.mcprotocollib.protocol.data.game.level.particle.ParticleType;
+import org.geysermc.mcprotocollib.protocol.data.game.recipe.RecipeType;
import java.util.*;
@@ -97,16 +93,6 @@ public final class Registries {
*/
public static final SimpleMappedRegistry BLOCK_ENTITIES = SimpleMappedRegistry.create("org.geysermc.geyser.translator.level.block.entity.BlockEntity", BlockEntityRegistryLoader::new);
- /**
- * A versioned registry which holds a {@link RecipeType} to a corresponding list of {@link RecipeData}.
- */
- public static final VersionedRegistry