aboutsummaryrefslogtreecommitdiffhomepage
path: root/patches/server/0641-Fix-upstreams-block-state-factories.patch
blob: ab5883e9507084c2030da226c545b6939760a404 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Wed, 6 Oct 2021 20:50:48 -0700
Subject: [PATCH] Fix upstreams block state factories

Sometimes, blocks are changed and then logic is called before the associated
tile entity is removed. When this happens, the factories were relying on the
block at the position, not the tile entity. This change prioritizes using the
tile entity type to determine the block state factory and falls back on
the material type of the block at that location.

== AT ==
public net.minecraft.world.level.block.entity.BlockEntityType validBlocks

diff --git a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java
index 6e24673a793017ee857cf75bf9a74105ce76b773..e3c5f99b3ad91a9bb454f9ab95b1ccff0bb7b34c 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java
@@ -371,7 +371,7 @@ public abstract class BlockEntity {
         // Paper end
         if (this.level == null) return null;
         org.bukkit.block.Block block = this.level.getWorld().getBlockAt(this.worldPosition.getX(), this.worldPosition.getY(), this.worldPosition.getZ());
-        if (block.getType() == org.bukkit.Material.AIR) return null;
+        // if (block.getType() == org.bukkit.Material.AIR) return null; // Paper - actually get the tile entity if it still exists
         org.bukkit.block.BlockState state = block.getState(useSnapshot); // Paper
         if (state instanceof InventoryHolder) return (InventoryHolder) state;
         return null;
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java
index 92133f16c192f5caf9962a08401ff914550747f8..397eb1a101bd60f49dbb2fa8eddf28f6f233167f 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java
@@ -20,7 +20,7 @@ import org.bukkit.persistence.PersistentDataContainer;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
-public class CraftBlockEntityState<T extends BlockEntity> extends CraftBlockState implements TileState {
+public abstract class CraftBlockEntityState<T extends BlockEntity> extends CraftBlockState implements TileState { // Paper - revert upstream's revert of the block state changes
 
     private final T tileEntity;
     private final T snapshot;
@@ -181,14 +181,10 @@ public class CraftBlockEntityState<T extends BlockEntity> extends CraftBlockStat
     }
 
     @Override
-    public CraftBlockEntityState<T> copy() {
-        return new CraftBlockEntityState<>(this, null);
-    }
+    public abstract CraftBlockEntityState<T> copy(); // Paper - make abstract
 
     @Override
-    public CraftBlockEntityState<T> copy(Location location) {
-        return new CraftBlockEntityState<>(this, location);
-    }
+    public abstract CraftBlockEntityState<T> copy(Location location); // Paper - make abstract
 
     // Paper start
     @Override
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockStates.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockStates.java
index 83ac5fc6cbbd249b5865ab203b150f53f01c9f05..6a25916aec7c8e0bc5cc18e3e06c6e07e0804380 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockStates.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockStates.java
@@ -22,6 +22,7 @@ import net.minecraft.world.level.block.entity.BeehiveBlockEntity;
 import net.minecraft.world.level.block.entity.BellBlockEntity;
 import net.minecraft.world.level.block.entity.BlastFurnaceBlockEntity;
 import net.minecraft.world.level.block.entity.BlockEntity;
+import net.minecraft.world.level.block.entity.BlockEntityType; // Paper
 import net.minecraft.world.level.block.entity.BrewingStandBlockEntity;
 import net.minecraft.world.level.block.entity.BrushableBlockEntity;
 import net.minecraft.world.level.block.entity.CalibratedSculkSensorBlockEntity;
@@ -118,228 +119,65 @@ public final class CraftBlockStates {
     private static final BlockStateFactory<?> DEFAULT_FACTORY = new BlockStateFactory<CraftBlockState>(CraftBlockState.class) {
         @Override
         public CraftBlockState createBlockState(World world, BlockPos blockPosition, net.minecraft.world.level.block.state.BlockState blockData, BlockEntity tileEntity) {
-            // SPIGOT-6754, SPIGOT-6817: Restore previous behaviour for tile entities with removed blocks (loot generation post-destroy)
-            if (tileEntity != null) {
-                // block with unhandled TileEntity:
-                return new CraftBlockEntityState<>(world, tileEntity);
-            }
+            // Paper - revert upstream's revert of the block state changes. Block entities that have already had the block type set to AIR are still valid, upstream decided to ignore them
             Preconditions.checkState(tileEntity == null, "Unexpected BlockState for %s", CraftBlockType.minecraftToBukkit(blockData.getBlock()));
             return new CraftBlockState(world, blockPosition, blockData);
         }
     };
+    // Paper start
+    private static final Map<BlockEntityType<?>, BlockStateFactory<?>> FACTORIES_BY_BLOCK_ENTITY_TYPE = new HashMap<>();
+    private static void register(BlockEntityType<?> type, BlockStateFactory<?> factory) {
+        FACTORIES_BY_BLOCK_ENTITY_TYPE.put(type, factory);
+    }
+    // Paper end
 
     static {
-        register(
-                Arrays.asList(
-                        Material.ACACIA_SIGN,
-                        Material.ACACIA_WALL_SIGN,
-                        Material.BAMBOO_SIGN,
-                        Material.BAMBOO_WALL_SIGN,
-                        Material.BIRCH_SIGN,
-                        Material.BIRCH_WALL_SIGN,
-                        Material.CHERRY_SIGN,
-                        Material.CHERRY_WALL_SIGN,
-                        Material.CRIMSON_SIGN,
-                        Material.CRIMSON_WALL_SIGN,
-                        Material.DARK_OAK_SIGN,
-                        Material.DARK_OAK_WALL_SIGN,
-                        Material.JUNGLE_SIGN,
-                        Material.JUNGLE_WALL_SIGN,
-                        Material.MANGROVE_SIGN,
-                        Material.MANGROVE_WALL_SIGN,
-                        Material.OAK_SIGN,
-                        Material.OAK_WALL_SIGN,
-                        Material.SPRUCE_SIGN,
-                        Material.SPRUCE_WALL_SIGN,
-                        Material.WARPED_SIGN,
-                        Material.WARPED_WALL_SIGN
-                ), CraftSign.class, CraftSign::new, SignBlockEntity::new
-        );
-
-        register(
-                Arrays.asList(
-                        Material.ACACIA_HANGING_SIGN,
-                        Material.ACACIA_WALL_HANGING_SIGN,
-                        Material.BAMBOO_HANGING_SIGN,
-                        Material.BAMBOO_WALL_HANGING_SIGN,
-                        Material.BIRCH_HANGING_SIGN,
-                        Material.BIRCH_WALL_HANGING_SIGN,
-                        Material.CHERRY_HANGING_SIGN,
-                        Material.CHERRY_WALL_HANGING_SIGN,
-                        Material.CRIMSON_HANGING_SIGN,
-                        Material.CRIMSON_WALL_HANGING_SIGN,
-                        Material.DARK_OAK_HANGING_SIGN,
-                        Material.DARK_OAK_WALL_HANGING_SIGN,
-                        Material.JUNGLE_HANGING_SIGN,
-                        Material.JUNGLE_WALL_HANGING_SIGN,
-                        Material.MANGROVE_HANGING_SIGN,
-                        Material.MANGROVE_WALL_HANGING_SIGN,
-                        Material.OAK_HANGING_SIGN,
-                        Material.OAK_WALL_HANGING_SIGN,
-                        Material.SPRUCE_HANGING_SIGN,
-                        Material.SPRUCE_WALL_HANGING_SIGN,
-                        Material.WARPED_HANGING_SIGN,
-                        Material.WARPED_WALL_HANGING_SIGN
-                ), CraftHangingSign.class, CraftHangingSign::new, HangingSignBlockEntity::new
-        );
-
-        register(
-                Arrays.asList(
-                        Material.CREEPER_HEAD,
-                        Material.CREEPER_WALL_HEAD,
-                        Material.DRAGON_HEAD,
-                        Material.DRAGON_WALL_HEAD,
-                        Material.PIGLIN_HEAD,
-                        Material.PIGLIN_WALL_HEAD,
-                        Material.PLAYER_HEAD,
-                        Material.PLAYER_WALL_HEAD,
-                        Material.SKELETON_SKULL,
-                        Material.SKELETON_WALL_SKULL,
-                        Material.WITHER_SKELETON_SKULL,
-                        Material.WITHER_SKELETON_WALL_SKULL,
-                        Material.ZOMBIE_HEAD,
-                        Material.ZOMBIE_WALL_HEAD
-                ), CraftSkull.class, CraftSkull::new, SkullBlockEntity::new
-        );
-
-        register(
-                Arrays.asList(
-                        Material.COMMAND_BLOCK,
-                        Material.REPEATING_COMMAND_BLOCK,
-                        Material.CHAIN_COMMAND_BLOCK
-                ), CraftCommandBlock.class, CraftCommandBlock::new, CommandBlockEntity::new
-        );
-
-        register(
-                Arrays.asList(
-                        Material.BLACK_BANNER,
-                        Material.BLACK_WALL_BANNER,
-                        Material.BLUE_BANNER,
-                        Material.BLUE_WALL_BANNER,
-                        Material.BROWN_BANNER,
-                        Material.BROWN_WALL_BANNER,
-                        Material.CYAN_BANNER,
-                        Material.CYAN_WALL_BANNER,
-                        Material.GRAY_BANNER,
-                        Material.GRAY_WALL_BANNER,
-                        Material.GREEN_BANNER,
-                        Material.GREEN_WALL_BANNER,
-                        Material.LIGHT_BLUE_BANNER,
-                        Material.LIGHT_BLUE_WALL_BANNER,
-                        Material.LIGHT_GRAY_BANNER,
-                        Material.LIGHT_GRAY_WALL_BANNER,
-                        Material.LIME_BANNER,
-                        Material.LIME_WALL_BANNER,
-                        Material.MAGENTA_BANNER,
-                        Material.MAGENTA_WALL_BANNER,
-                        Material.ORANGE_BANNER,
-                        Material.ORANGE_WALL_BANNER,
-                        Material.PINK_BANNER,
-                        Material.PINK_WALL_BANNER,
-                        Material.PURPLE_BANNER,
-                        Material.PURPLE_WALL_BANNER,
-                        Material.RED_BANNER,
-                        Material.RED_WALL_BANNER,
-                        Material.WHITE_BANNER,
-                        Material.WHITE_WALL_BANNER,
-                        Material.YELLOW_BANNER,
-                        Material.YELLOW_WALL_BANNER
-                ), CraftBanner.class, CraftBanner::new, BannerBlockEntity::new
-        );
-
-        register(
-                Arrays.asList(
-                        Material.SHULKER_BOX,
-                        Material.WHITE_SHULKER_BOX,
-                        Material.ORANGE_SHULKER_BOX,
-                        Material.MAGENTA_SHULKER_BOX,
-                        Material.LIGHT_BLUE_SHULKER_BOX,
-                        Material.YELLOW_SHULKER_BOX,
-                        Material.LIME_SHULKER_BOX,
-                        Material.PINK_SHULKER_BOX,
-                        Material.GRAY_SHULKER_BOX,
-                        Material.LIGHT_GRAY_SHULKER_BOX,
-                        Material.CYAN_SHULKER_BOX,
-                        Material.PURPLE_SHULKER_BOX,
-                        Material.BLUE_SHULKER_BOX,
-                        Material.BROWN_SHULKER_BOX,
-                        Material.GREEN_SHULKER_BOX,
-                        Material.RED_SHULKER_BOX,
-                        Material.BLACK_SHULKER_BOX
-                ), CraftShulkerBox.class, CraftShulkerBox::new, ShulkerBoxBlockEntity::new
-        );
-
-        register(
-                Arrays.asList(
-                        Material.BLACK_BED,
-                        Material.BLUE_BED,
-                        Material.BROWN_BED,
-                        Material.CYAN_BED,
-                        Material.GRAY_BED,
-                        Material.GREEN_BED,
-                        Material.LIGHT_BLUE_BED,
-                        Material.LIGHT_GRAY_BED,
-                        Material.LIME_BED,
-                        Material.MAGENTA_BED,
-                        Material.ORANGE_BED,
-                        Material.PINK_BED,
-                        Material.PURPLE_BED,
-                        Material.RED_BED,
-                        Material.WHITE_BED,
-                        Material.YELLOW_BED
-                ), CraftBed.class, CraftBed::new, BedBlockEntity::new
-        );
-
-        register(
-                Arrays.asList(
-                        Material.BEEHIVE,
-                        Material.BEE_NEST
-                ), CraftBeehive.class, CraftBeehive::new, BeehiveBlockEntity::new
-        );
-
-        register(
-                Arrays.asList(
-                        Material.CAMPFIRE,
-                        Material.SOUL_CAMPFIRE
-                ), CraftCampfire.class, CraftCampfire::new, CampfireBlockEntity::new
-        );
-
-        register(Material.BARREL, CraftBarrel.class, CraftBarrel::new, BarrelBlockEntity::new);
-        register(Material.BEACON, CraftBeacon.class, CraftBeacon::new, BeaconBlockEntity::new);
-        register(Material.BELL, CraftBell.class, CraftBell::new, BellBlockEntity::new);
-        register(Material.BLAST_FURNACE, CraftBlastFurnace.class, CraftBlastFurnace::new, BlastFurnaceBlockEntity::new);
-        register(Material.BREWING_STAND, CraftBrewingStand.class, CraftBrewingStand::new, BrewingStandBlockEntity::new);
-        register(Material.CHEST, CraftChest.class, CraftChest::new, ChestBlockEntity::new);
-        register(Material.CHISELED_BOOKSHELF, CraftChiseledBookshelf.class, CraftChiseledBookshelf::new, ChiseledBookShelfBlockEntity::new);
-        register(Material.COMPARATOR, CraftComparator.class, CraftComparator::new, ComparatorBlockEntity::new);
-        register(Material.CONDUIT, CraftConduit.class, CraftConduit::new, ConduitBlockEntity::new);
-        register(Material.DAYLIGHT_DETECTOR, CraftDaylightDetector.class, CraftDaylightDetector::new, DaylightDetectorBlockEntity::new);
-        register(Material.DECORATED_POT, CraftDecoratedPot.class, CraftDecoratedPot::new, DecoratedPotBlockEntity::new);
-        register(Material.DISPENSER, CraftDispenser.class, CraftDispenser::new, DispenserBlockEntity::new);
-        register(Material.DROPPER, CraftDropper.class, CraftDropper::new, DropperBlockEntity::new);
-        register(Material.ENCHANTING_TABLE, CraftEnchantingTable.class, CraftEnchantingTable::new, EnchantingTableBlockEntity::new);
-        register(Material.ENDER_CHEST, CraftEnderChest.class, CraftEnderChest::new, EnderChestBlockEntity::new);
-        register(Material.END_GATEWAY, CraftEndGateway.class, CraftEndGateway::new, TheEndGatewayBlockEntity::new);
-        register(Material.END_PORTAL, CraftEndPortal.class, CraftEndPortal::new, TheEndPortalBlockEntity::new);
-        register(Material.FURNACE, CraftFurnaceFurnace.class, CraftFurnaceFurnace::new, FurnaceBlockEntity::new);
-        register(Material.HOPPER, CraftHopper.class, CraftHopper::new, HopperBlockEntity::new);
-        register(Material.JIGSAW, CraftJigsaw.class, CraftJigsaw::new, JigsawBlockEntity::new);
-        register(Material.JUKEBOX, CraftJukebox.class, CraftJukebox::new, JukeboxBlockEntity::new);
-        register(Material.LECTERN, CraftLectern.class, CraftLectern::new, LecternBlockEntity::new);
-        register(Material.MOVING_PISTON, CraftMovingPiston.class, CraftMovingPiston::new, PistonMovingBlockEntity::new);
-        register(Material.SCULK_CATALYST, CraftSculkCatalyst.class, CraftSculkCatalyst::new, SculkCatalystBlockEntity::new);
-        register(Material.CALIBRATED_SCULK_SENSOR, CraftCalibratedSculkSensor.class, CraftCalibratedSculkSensor::new, CalibratedSculkSensorBlockEntity::new);
-        register(Material.SCULK_SENSOR, CraftSculkSensor.class, CraftSculkSensor::new, SculkSensorBlockEntity::new);
-        register(Material.SCULK_SHRIEKER, CraftSculkShrieker.class, CraftSculkShrieker::new, SculkShriekerBlockEntity::new);
-        register(Material.SMOKER, CraftSmoker.class, CraftSmoker::new, SmokerBlockEntity::new);
-        register(Material.SPAWNER, CraftCreatureSpawner.class, CraftCreatureSpawner::new, SpawnerBlockEntity::new);
-        register(Material.STRUCTURE_BLOCK, CraftStructureBlock.class, CraftStructureBlock::new, StructureBlockEntity::new);
-        register(Material.SUSPICIOUS_SAND, CraftSuspiciousSand.class, CraftSuspiciousSand::new, BrushableBlockEntity::new);
-        register(Material.SUSPICIOUS_GRAVEL, CraftBrushableBlock.class, CraftBrushableBlock::new, BrushableBlockEntity::new);
-        register(Material.TRAPPED_CHEST, CraftChest.class, CraftChest::new, TrappedChestBlockEntity::new);
-        register(Material.CRAFTER, CraftCrafter.class, CraftCrafter::new, CrafterBlockEntity::new);
-        register(Material.TRIAL_SPAWNER, CraftTrialSpawner.class, CraftTrialSpawner::new, TrialSpawnerBlockEntity::new);
-        register(Material.VAULT, CraftVault.class, CraftVault::new, VaultBlockEntity::new);
+        // Paper start - simplify
+        register(BlockEntityType.SIGN, CraftSign.class, CraftSign::new);
+        register(BlockEntityType.HANGING_SIGN, CraftHangingSign.class, CraftHangingSign::new);
+        register(BlockEntityType.SKULL, CraftSkull.class, CraftSkull::new);
+        register(BlockEntityType.COMMAND_BLOCK, CraftCommandBlock.class, CraftCommandBlock::new);
+        register(BlockEntityType.BANNER, CraftBanner.class, CraftBanner::new);
+        register(BlockEntityType.SHULKER_BOX, CraftShulkerBox.class, CraftShulkerBox::new);
+        register(BlockEntityType.BED, CraftBed.class, CraftBed::new);
+        register(BlockEntityType.BEEHIVE, CraftBeehive.class, CraftBeehive::new);
+        register(BlockEntityType.CAMPFIRE, CraftCampfire.class, CraftCampfire::new);
+        register(BlockEntityType.BARREL, CraftBarrel.class, CraftBarrel::new);
+        register(BlockEntityType.BEACON, CraftBeacon.class, CraftBeacon::new);
+        register(BlockEntityType.BELL, CraftBell.class, CraftBell::new);
+        register(BlockEntityType.BLAST_FURNACE, CraftBlastFurnace.class, CraftBlastFurnace::new);
+        register(BlockEntityType.BREWING_STAND, CraftBrewingStand.class, CraftBrewingStand::new);
+        register(BlockEntityType.CHEST, CraftChest.class, CraftChest::new);
+        register(BlockEntityType.CHISELED_BOOKSHELF, CraftChiseledBookshelf.class, CraftChiseledBookshelf::new);
+        register(BlockEntityType.COMPARATOR, CraftComparator.class, CraftComparator::new);
+        register(BlockEntityType.CONDUIT, CraftConduit.class, CraftConduit::new);
+        register(BlockEntityType.DAYLIGHT_DETECTOR, CraftDaylightDetector.class, CraftDaylightDetector::new);
+        register(BlockEntityType.DECORATED_POT, CraftDecoratedPot.class, CraftDecoratedPot::new);
+        register(BlockEntityType.DISPENSER, CraftDispenser.class, CraftDispenser::new);
+        register(BlockEntityType.DROPPER, CraftDropper.class, CraftDropper::new);
+        register(BlockEntityType.ENCHANTING_TABLE, CraftEnchantingTable.class, CraftEnchantingTable::new);
+        register(BlockEntityType.ENDER_CHEST, CraftEnderChest.class, CraftEnderChest::new);
+        register(BlockEntityType.END_GATEWAY, CraftEndGateway.class, CraftEndGateway::new);
+        register(BlockEntityType.END_PORTAL, CraftEndPortal.class, CraftEndPortal::new);
+        register(BlockEntityType.FURNACE, CraftFurnaceFurnace.class, CraftFurnaceFurnace::new);
+        register(BlockEntityType.HOPPER, CraftHopper.class, CraftHopper::new);
+        register(BlockEntityType.JIGSAW, CraftJigsaw.class, CraftJigsaw::new);
+        register(BlockEntityType.JUKEBOX, CraftJukebox.class, CraftJukebox::new);
+        register(BlockEntityType.LECTERN, CraftLectern.class, CraftLectern::new);
+        register(BlockEntityType.PISTON, CraftMovingPiston.class, CraftMovingPiston::new);
+        register(BlockEntityType.SCULK_CATALYST, CraftSculkCatalyst.class, CraftSculkCatalyst::new);
+        register(BlockEntityType.SCULK_SENSOR, CraftSculkSensor.class, CraftSculkSensor::new);
+        register(BlockEntityType.SCULK_SHRIEKER, CraftSculkShrieker.class, CraftSculkShrieker::new);
+        register(BlockEntityType.CALIBRATED_SCULK_SENSOR, CraftCalibratedSculkSensor.class, CraftCalibratedSculkSensor::new);
+        register(BlockEntityType.SMOKER, CraftSmoker.class, CraftSmoker::new);
+        register(BlockEntityType.MOB_SPAWNER, CraftCreatureSpawner.class, CraftCreatureSpawner::new);
+        register(BlockEntityType.STRUCTURE_BLOCK, CraftStructureBlock.class, CraftStructureBlock::new);
+        register(BlockEntityType.BRUSHABLE_BLOCK, CraftBrushableBlock.class, CraftBrushableBlock::new); // note: spigot still uses CraftSuspiciousSand impl for that block type
+        register(BlockEntityType.TRAPPED_CHEST, CraftChest.class, CraftChest::new);
+        register(BlockEntityType.CRAFTER, CraftCrafter.class, CraftCrafter::new);
+        register(BlockEntityType.TRIAL_SPAWNER, CraftTrialSpawner.class, CraftTrialSpawner::new);
+        register(BlockEntityType.VAULT, CraftVault.class, CraftVault::new);
+        // Paper end
     }
 
     private static void register(Material blockType, BlockStateFactory<?> factory) {
@@ -347,30 +185,33 @@ public final class CraftBlockStates {
     }
 
     private static <T extends BlockEntity, B extends CraftBlockEntityState<T>> void register(
-            Material blockType,
-            Class<B> blockStateType,
-            BiFunction<World, T, B> blockStateConstructor,
-            BiFunction<BlockPos, net.minecraft.world.level.block.state.BlockState, T> tileEntityConstructor
-    ) {
-        CraftBlockStates.register(Collections.singletonList(blockType), blockStateType, blockStateConstructor, tileEntityConstructor);
-    }
-
-    private static <T extends BlockEntity, B extends CraftBlockEntityState<T>> void register(
-            List<Material> blockTypes,
+            net.minecraft.world.level.block.entity.BlockEntityType<? extends T> blockEntityType, // Paper
             Class<B> blockStateType,
-            BiFunction<World, T, B> blockStateConstructor,
-            BiFunction<BlockPos, net.minecraft.world.level.block.state.BlockState, T> tileEntityConstructor
+            BiFunction<World, T, B> blockStateConstructor // Paper
     ) {
-        BlockStateFactory<B> factory = new BlockEntityStateFactory<>(blockStateType, blockStateConstructor, tileEntityConstructor);
-        for (Material blockType : blockTypes) {
-            CraftBlockStates.register(blockType, factory);
+        // Paper start
+        BlockStateFactory<B> factory = new BlockEntityStateFactory<>(blockStateType, blockStateConstructor, blockEntityType::create);
+        for (net.minecraft.world.level.block.Block block : blockEntityType.validBlocks) {
+            CraftBlockStates.register(CraftBlockType.minecraftToBukkit(block), factory);
         }
+        CraftBlockStates.register(blockEntityType, factory);
+        // Paper end
     }
 
     private static BlockStateFactory<?> getFactory(Material material) {
         return CraftBlockStates.FACTORIES.getOrDefault(material, CraftBlockStates.DEFAULT_FACTORY);
     }
 
+    // Paper start
+    private static BlockStateFactory<?> getFactory(Material material, BlockEntityType<?> type) {
+        if (type != null) {
+            return CraftBlockStates.FACTORIES_BY_BLOCK_ENTITY_TYPE.getOrDefault(type, getFactory(material));
+        } else {
+            return getFactory(material);
+        }
+    }
+    // Paper end
+
     public static Class<? extends CraftBlockState> getBlockStateType(Material material) {
         Preconditions.checkNotNull(material, "material is null");
         return CraftBlockStates.getFactory(material).blockStateType;
@@ -386,6 +227,13 @@ public final class CraftBlockStates {
         return null;
     }
 
+    // Paper start
+    public static Class<? extends CraftBlockState> getBlockStateType(BlockEntityType<?> blockEntityType) {
+        Preconditions.checkNotNull(blockEntityType, "blockEntityType is null");
+        return CraftBlockStates.getFactory(null, blockEntityType).blockStateType;
+    }
+    // Paper end
+
     public static BlockState getBlockState(Block block) {
         // Paper start
         return CraftBlockStates.getBlockState(block, true);
@@ -453,7 +301,7 @@ public final class CraftBlockStates {
         if (world != null && tileEntity == null && CraftBlockStates.isTileEntityOptional(material)) {
             factory = CraftBlockStates.DEFAULT_FACTORY;
         } else {
-            factory = CraftBlockStates.getFactory(material);
+            factory = CraftBlockStates.getFactory(material, tileEntity != null ? tileEntity.getType() : null); // Paper
         }
         return factory.createBlockState(world, blockPosition, blockData, tileEntity);
     }
diff --git a/src/test/java/org/bukkit/craftbukkit/block/BlockStateTest.java b/src/test/java/org/bukkit/craftbukkit/block/BlockStateTest.java
index 81d4c8867ebcba1b805be1828e0a6a476963a855..9ff1a8068533ba5fc2fb43188d9a5c544a907618 100644
--- a/src/test/java/org/bukkit/craftbukkit/block/BlockStateTest.java
+++ b/src/test/java/org/bukkit/craftbukkit/block/BlockStateTest.java
@@ -7,6 +7,7 @@ import net.minecraft.core.registries.BuiltInRegistries;
 import net.minecraft.world.level.block.Block;
 import net.minecraft.world.level.block.EntityBlock;
 import net.minecraft.world.level.block.entity.BlockEntity;
+import net.minecraft.world.level.block.entity.BlockEntityType;
 import org.bukkit.Material;
 import org.bukkit.support.AbstractTestingBase;
 import org.junit.jupiter.api.Test;
@@ -41,4 +42,13 @@ public class BlockStateTest extends AbstractTestingBase {
             }
         }
     }
+
+    // Paper start
+    @Test
+    public void testBlockEntityTypes() {
+        for (var blockEntityType : BuiltInRegistries.BLOCK_ENTITY_TYPE) {
+            org.junit.jupiter.api.Assertions.assertNotNull(CraftBlockStates.getBlockStateType(blockEntityType));
+        }
+    }
+    // Paper end
 }