Skip to content

Commit db9d8e3

Browse files
tastybentoBONNe
andauthored
New version 1.14.0 (#17)
* Update pom.xml * Update to Minecraft 1.18 biome changes * Update pom.xml 1.13.0 * Update to latest Minecraft API * Added test class * Add distribution management section to POM * Update to MC 1.21.4 and CodeMC changes (#16) --------- Co-authored-by: BONNe <bonne@bonne.id.lv>
1 parent e4ede61 commit db9d8e3

3 files changed

Lines changed: 139 additions & 10 deletions

File tree

pom.xml

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,9 @@
3030
</issueManagement>
3131

3232
<distributionManagement>
33-
<snapshotRepository>
34-
<id>codemc-snapshots</id>
35-
<url>https://repo.codemc.org/repository/maven-snapshots</url>
36-
</snapshotRepository>
3733
<repository>
38-
<id>codemc-releases</id>
39-
<url>https://repo.codemc.org/repository/maven-releases</url>
34+
<id>bentoboxworld</id>
35+
<url>https://repo.codemc.org/repository/bentoboxworld</url>
4036
</repository>
4137
</distributionManagement>
4238

@@ -46,8 +42,8 @@
4642
<java.version>17</java.version>
4743
<powermock.version>2.0.9</powermock.version>
4844
<!-- More visible way how to change dependency versions -->
49-
<spigot.version>1.20.4-R0.1-SNAPSHOT</spigot.version>
50-
<bentobox.version>2.0.0-SNAPSHOT</bentobox.version>
45+
<spigot.version>1.21.3-R0.1-SNAPSHOT</spigot.version>
46+
<bentobox.version>2.7.1-SNAPSHOT</bentobox.version>
5147
<!-- Revision variable removes warning about dynamic version -->
5248
<revision>${build.version}-SNAPSHOT</revision>
5349
<!-- This allows to change between versions and snapshots. -->
@@ -56,7 +52,7 @@
5652
X.Y.Z -> BentoBox core version
5753
.M -> Addon development iteration.
5854
-->
59-
<build.version>1.13</build.version>
55+
<build.version>1.14.0</build.version>
6056
<build.number>-LOCAL</build.number>
6157
</properties>
6258

@@ -107,6 +103,10 @@
107103
<id>spigot-repo</id>
108104
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots</url>
109105
</repository>
106+
<repository>
107+
<id>bentoboxworld</id>
108+
<url>https://repo.codemc.org/repository/bentoboxworld/</url>
109+
</repository>
110110
<repository>
111111
<id>codemc</id>
112112
<url>https://repo.codemc.org/repository/maven-snapshots/</url>

src/test/java/world/bentobox/extramobs/listeners/MobsSpawnListenerTest.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,22 @@
1818
import org.bukkit.entity.Fish;
1919
import org.bukkit.event.entity.CreatureSpawnEvent;
2020
import org.eclipse.jdt.annotation.NonNull;
21+
import org.junit.After;
2122
import org.junit.Before;
2223
import org.junit.Test;
2324
import org.junit.runner.RunWith;
2425
import org.mockito.Mock;
26+
import org.mockito.Mockito;
2527
import org.powermock.modules.junit4.PowerMockRunner;
2628

2729
import world.bentobox.bentobox.BentoBox;
2830
import world.bentobox.bentobox.api.addons.AddonDescription;
2931
import world.bentobox.bentobox.api.addons.GameModeAddon;
32+
import world.bentobox.bentobox.api.user.User;
3033
import world.bentobox.bentobox.managers.IslandWorldManager;
3134
import world.bentobox.extramobs.ExtraMobsAddon;
3235
import world.bentobox.extramobs.config.Settings;
36+
import world.bentobox.extramobs.listeners.mocks.ServerMocks;
3337

3438
@RunWith(PowerMockRunner.class)
3539
public class MobsSpawnListenerTest {
@@ -64,6 +68,7 @@ public class MobsSpawnListenerTest {
6468

6569
@Before
6670
public void setUp() {
71+
ServerMocks.newServer();
6772
settings = new Settings();
6873
when(addon.getSettings()).thenReturn(settings);
6974

@@ -93,6 +98,13 @@ public void setUp() {
9398
listener = new MobsSpawnListener(addon);
9499
}
95100

101+
@After
102+
public void tearDown() {
103+
ServerMocks.unsetBukkitServer();
104+
User.clearUsers();
105+
Mockito.framework().clearInlineMocks();
106+
}
107+
96108
// Test case for natural spawning of Zombified Piglin in the Nether
97109
@Test
98110
public void testNaturalSpawnZombifiedPiglinNether() {
@@ -136,7 +148,6 @@ public void testFishSpawnDeepOcean() {
136148
when(event.getSpawnReason()).thenReturn(CreatureSpawnEvent.SpawnReason.NATURAL);
137149
when(event.getLocation()).thenReturn(location);
138150
when(world.getEnvironment()).thenReturn(World.Environment.NORMAL);
139-
when(world.getBiome(anyInt(), anyInt(), anyInt())).thenReturn(Biome.DEEP_OCEAN);
140151
settings.setGuardianChance(1.1); // Set so that it will always spawn
141152
when(block.getType()).thenReturn(Material.WATER, Material.WATER, Material.WATER, Material.PRISMARINE);
142153

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
package world.bentobox.extramobs.listeners.mocks;
2+
3+
import static org.mockito.ArgumentMatchers.notNull;
4+
import static org.mockito.Mockito.doAnswer;
5+
import static org.mockito.Mockito.doReturn;
6+
import static org.mockito.Mockito.mock;
7+
import static org.mockito.Mockito.when;
8+
9+
import java.lang.reflect.Field;
10+
import java.util.HashMap;
11+
import java.util.Locale;
12+
import java.util.Map;
13+
import java.util.Set;
14+
import java.util.logging.Logger;
15+
16+
import org.bukkit.Bukkit;
17+
import org.bukkit.Keyed;
18+
import org.bukkit.NamespacedKey;
19+
import org.bukkit.Registry;
20+
import org.bukkit.Server;
21+
import org.bukkit.Tag;
22+
import org.bukkit.UnsafeValues;
23+
import org.eclipse.jdt.annotation.NonNull;
24+
25+
public final class ServerMocks {
26+
27+
public static @NonNull Server newServer() {
28+
Server mock = mock(Server.class);
29+
30+
Logger noOp = mock(Logger.class);
31+
when(mock.getLogger()).thenReturn(noOp);
32+
when(mock.isPrimaryThread()).thenReturn(true);
33+
34+
// Unsafe
35+
UnsafeValues unsafe = mock(UnsafeValues.class);
36+
when(mock.getUnsafe()).thenReturn(unsafe);
37+
38+
// Server must be available before tags can be mocked.
39+
Bukkit.setServer(mock);
40+
41+
// Bukkit has a lot of static constants referencing registry values. To initialize those, the
42+
// registries must be able to be fetched before the classes are touched.
43+
Map<Class<? extends Keyed>, Object> registers = new HashMap<>();
44+
45+
doAnswer(invocationGetRegistry -> registers.computeIfAbsent(invocationGetRegistry.getArgument(0), clazz -> {
46+
Registry<?> registry = mock(Registry.class);
47+
Map<NamespacedKey, Keyed> cache = new HashMap<>();
48+
doAnswer(invocationGetEntry -> {
49+
NamespacedKey key = invocationGetEntry.getArgument(0);
50+
// Some classes (like BlockType and ItemType) have extra generics that will be
51+
// erased during runtime calls. To ensure accurate typing, grab the constant's field.
52+
// This approach also allows us to return null for unsupported keys.
53+
Class<? extends Keyed> constantClazz;
54+
try {
55+
//noinspection unchecked
56+
constantClazz = (Class<? extends Keyed>) clazz
57+
.getField(key.getKey().toUpperCase(Locale.ROOT).replace('.', '_')).getType();
58+
} catch (ClassCastException e) {
59+
throw new RuntimeException(e);
60+
} catch (NoSuchFieldException e) {
61+
return null;
62+
}
63+
64+
return cache.computeIfAbsent(key, key1 -> {
65+
Keyed keyed = mock(constantClazz);
66+
doReturn(key).when(keyed).getKey();
67+
return keyed;
68+
});
69+
}).when(registry).get(notNull());
70+
return registry;
71+
})).when(mock).getRegistry(notNull());
72+
73+
// Tags are dependent on registries, but use a different method.
74+
// This will set up blank tags for each constant; all that needs to be done to render them
75+
// functional is to re-mock Tag#getValues.
76+
doAnswer(invocationGetTag -> {
77+
Tag<?> tag = mock(Tag.class);
78+
doReturn(invocationGetTag.getArgument(1)).when(tag).getKey();
79+
doReturn(Set.of()).when(tag).getValues();
80+
doAnswer(invocationIsTagged -> {
81+
Keyed keyed = invocationIsTagged.getArgument(0);
82+
Class<?> type = invocationGetTag.getArgument(2);
83+
if (!type.isAssignableFrom(keyed.getClass())) {
84+
return null;
85+
}
86+
// Since these are mocks, the exact instance might not be equal. Consider equal keys equal.
87+
return tag.getValues().contains(keyed)
88+
|| tag.getValues().stream().anyMatch(value -> value.getKey().equals(keyed.getKey()));
89+
}).when(tag).isTagged(notNull());
90+
return tag;
91+
}).when(mock).getTag(notNull(), notNull(), notNull());
92+
93+
// Once the server is all set up, touch BlockType and ItemType to initialize.
94+
// This prevents issues when trying to access dependent methods from a Material constant.
95+
try {
96+
Class.forName("org.bukkit.inventory.ItemType");
97+
Class.forName("org.bukkit.block.BlockType");
98+
} catch (ClassNotFoundException e) {
99+
throw new RuntimeException(e);
100+
}
101+
102+
return mock;
103+
}
104+
105+
public static void unsetBukkitServer() {
106+
try {
107+
Field server = Bukkit.class.getDeclaredField("server");
108+
server.setAccessible(true);
109+
server.set(null, null);
110+
} catch (NoSuchFieldException | IllegalArgumentException | IllegalAccessException e) {
111+
throw new RuntimeException(e);
112+
}
113+
}
114+
115+
private ServerMocks() {
116+
}
117+
118+
}

0 commit comments

Comments
 (0)