package pluginbase.testingbukkit; import org.bukkit.*; import org.bukkit.World.Environment; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; import pluginbase.config.SerializableConfig; import pluginbase.config.annotation.SerializableAs; import pluginbase.config.annotation.SerializeWith; import pluginbase.config.datasource.DataSource; import pluginbase.config.datasource.hocon.HoconDataSource; import pluginbase.config.serializers.Serializer; import pluginbase.config.serializers.SerializerSet; import pluginbase.testingbukkit.answers.NoArgVoidAnswer; import pluginbase.testingbukkit.answers.SetterAnswer; import java.io.File; import java.util.HashMap; import java.util.Map; import java.util.UUID; import static org.mockito.Matchers.*; import static org.powermock.api.mockito.PowerMockito.*; public final class WorldFactory { @SerializableAs("World") private static class WorldData { static { SerializableConfig.registerSerializableAsClass(WorldData.class); } String name; @SerializeWith(UUIDSerializer.class) UUID uuid; WorldType type = WorldType.NORMAL; Environment environment; long seed = 0L; transient long time = 0L; boolean pvp = true; boolean keepSpawnInMemory = true; Difficulty difficulty = Difficulty.EASY; @SerializeWith(LocationSerializer.class) Location spawn = new Location(null, 0, 0, 0); transient File folder; transient File datFile; private WorldData() { } private WorldData(WorldCreator creator, World mockedWorld) { this.name = creator.name(); this.environment = creator.environment(); this.type = creator.type(); this.seed = creator.seed(); this.uuid = UUID.nameUUIDFromBytes(name.getBytes()); folder = new File(FileLocations.WORLDS_DIRECTORY, name); datFile = new File(folder, "level.dat"); if (!datFile.exists()) { save(); } else { try { DataSource dataSource = HoconDataSource.builder().setFile(datFile).build(); WorldData world = (WorldData) dataSource.load(); if (world != null) { this.type = world.type; this.seed = world.seed; this.uuid = world.uuid; this.environment = world.environment; this.spawn = new Location(mockedWorld, world.spawn.getX(), world.spawn.getY(), world.spawn.getZ(), world.spawn.getYaw(), world.spawn.getPitch()); this.difficulty = world.difficulty; this.pvp = world.pvp; this.keepSpawnInMemory = world.keepSpawnInMemory; } else { save(); } } catch (Exception e) { e.printStackTrace(); } } } public void save() { try { if (!datFile.exists()) { folder.mkdirs(); datFile.createNewFile(); } DataSource dataSource = HoconDataSource.builder().setFile(datFile).build(); dataSource.save(this); } catch (Exception e) { e.printStackTrace(); } } private static class UUIDSerializer implements Serializer<UUID> { @Nullable @Override public Object serialize(@Nullable UUID uuid, @NotNull SerializerSet serializerSet) { return uuid != null ? uuid.toString() : null; } @Nullable @Override public UUID deserialize(@Nullable Object o, @NotNull Class uuidClass, @NotNull SerializerSet serializerSet) throws IllegalArgumentException { return o != null ? UUID.fromString(o.toString()) : null; } } private static class LocationSerializer implements Serializer<Location> { @Nullable @Override public Object serialize(@Nullable Location l, @NotNull SerializerSet serializerSet) { if (l == null) { return null; } Map<String, Object> map = new HashMap<String, Object>(3); map.put("x", l.getX()); map.put("y", l.getY()); map.put("z", l.getZ()); return map; } @Nullable @Override public Location deserialize(@Nullable Object serialized, @NotNull Class wantedType, @NotNull SerializerSet serializerSet) throws IllegalArgumentException { if (serialized == null || !(serialized instanceof Map)) { return null; } Map map = (Map) serialized; double x = 0, y = 0, z = 0; try { x = Double.valueOf(map.get("x").toString()); y = Double.valueOf(map.get("y").toString()); z = Double.valueOf(map.get("z").toString()); } catch (Exception ignore) { } return new Location(null, x, y, z); } } } public static World createWorld(WorldCreator creator) { final World world = mock(World.class); final WorldData data = new WorldData(creator, world); doAnswer(new NoArgVoidAnswer() { @Override public void call() { data.save(); } }).when(world).save(); when(world.getName()).thenReturn(data.name); when(world.getUID()).thenReturn(data.uuid); when(world.getSpawnLocation()).thenAnswer(new Answer<Location>() { @Override public Location answer(InvocationOnMock invocationOnMock) throws Throwable { return data.spawn; } }); when(world.setSpawnLocation(anyInt(), anyInt(), anyInt())).thenAnswer(new Answer<Boolean>() { @Override public Boolean answer(InvocationOnMock invocationOnMock) throws Throwable { data.spawn = new Location(world, (Integer) invocationOnMock.getArguments()[0], (Integer) invocationOnMock.getArguments()[1], (Integer) invocationOnMock.getArguments()[2]); return true; } }); when(world.getTime()).thenAnswer(new Answer<Long>() { @Override public Long answer(InvocationOnMock invocationOnMock) throws Throwable { return data.time; } }); doAnswer(new SetterAnswer<Long>() { @Override public void set(Long value) { data.time = value; } }).when(world).setTime(anyLong()); when(world.getFullTime()).thenAnswer(new Answer<Long>() { @Override public Long answer(InvocationOnMock invocationOnMock) throws Throwable { return data.time; } }); doAnswer(new SetterAnswer<Long>() { @Override public void set(Long value) { data.time = value; } }).when(world).setFullTime(anyLong()); when(world.getEnvironment()).thenReturn(data.environment); when(world.getSeed()).thenReturn(data.seed); when(world.getPVP()).thenAnswer(new Answer<Boolean>() { @Override public Boolean answer(InvocationOnMock invocationOnMock) throws Throwable { return data.pvp; } }); doAnswer(new SetterAnswer<Boolean>() { @Override protected void set(Boolean value) { data.pvp = value; } }).when(world).setPVP(anyBoolean()); when(world.getKeepSpawnInMemory()).thenAnswer(new Answer<Boolean>() { @Override public Boolean answer(InvocationOnMock invocationOnMock) throws Throwable { return data.keepSpawnInMemory; } }); doAnswer(new SetterAnswer<Boolean>() { @Override protected void set(Boolean value) { data.keepSpawnInMemory = value; } }).when(world).setKeepSpawnInMemory(anyBoolean()); when(world.getDifficulty()).thenAnswer(new Answer<Difficulty>() { @Override public Difficulty answer(InvocationOnMock invocationOnMock) throws Throwable { return data.difficulty; } }); doAnswer(new SetterAnswer<Difficulty>() { @Override protected void set(Difficulty value) { data.difficulty = value; } }).when(world).setDifficulty(any(Difficulty.class)); when(world.getWorldFolder()).thenReturn(data.folder); when(world.getWorldType()).thenReturn(data.type); return world; } private WorldFactory() { } }