Fix 1.14 NoSuchMethodError. Dramatically improved multi world plugin compatibility. (#14)
This commit is contained in:
parent
aff33be4ce
commit
6507484079
|
@ -9,9 +9,11 @@ import com.mojang.datafixers.DataFixer;
|
||||||
import io.izzel.arclight.common.bridge.command.ICommandSourceBridge;
|
import io.izzel.arclight.common.bridge.command.ICommandSourceBridge;
|
||||||
import io.izzel.arclight.common.bridge.server.MinecraftServerBridge;
|
import io.izzel.arclight.common.bridge.server.MinecraftServerBridge;
|
||||||
import io.izzel.arclight.common.bridge.world.WorldBridge;
|
import io.izzel.arclight.common.bridge.world.WorldBridge;
|
||||||
|
import io.izzel.arclight.common.bridge.world.dimension.DimensionTypeBridge;
|
||||||
import io.izzel.arclight.common.mod.ArclightConstants;
|
import io.izzel.arclight.common.mod.ArclightConstants;
|
||||||
import io.izzel.arclight.common.mod.server.BukkitRegistry;
|
import io.izzel.arclight.common.mod.server.BukkitRegistry;
|
||||||
import io.izzel.arclight.common.mod.util.BukkitOptionParser;
|
import io.izzel.arclight.common.mod.util.BukkitOptionParser;
|
||||||
|
import it.unimi.dsi.fastutil.longs.LongIterator;
|
||||||
import joptsimple.OptionParser;
|
import joptsimple.OptionParser;
|
||||||
import joptsimple.OptionSet;
|
import joptsimple.OptionSet;
|
||||||
import net.minecraft.command.CommandSource;
|
import net.minecraft.command.CommandSource;
|
||||||
|
@ -23,15 +25,24 @@ import net.minecraft.profiler.DebugProfiler;
|
||||||
import net.minecraft.server.MinecraftServer;
|
import net.minecraft.server.MinecraftServer;
|
||||||
import net.minecraft.server.management.PlayerProfileCache;
|
import net.minecraft.server.management.PlayerProfileCache;
|
||||||
import net.minecraft.util.SharedConstants;
|
import net.minecraft.util.SharedConstants;
|
||||||
|
import net.minecraft.util.Unit;
|
||||||
import net.minecraft.util.Util;
|
import net.minecraft.util.Util;
|
||||||
import net.minecraft.util.concurrent.RecursiveEventLoop;
|
import net.minecraft.util.concurrent.RecursiveEventLoop;
|
||||||
import net.minecraft.util.concurrent.TickDelayedTask;
|
import net.minecraft.util.concurrent.TickDelayedTask;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.util.math.ChunkPos;
|
||||||
|
import net.minecraft.util.text.ITextComponent;
|
||||||
import net.minecraft.util.text.StringTextComponent;
|
import net.minecraft.util.text.StringTextComponent;
|
||||||
|
import net.minecraft.util.text.TranslationTextComponent;
|
||||||
|
import net.minecraft.world.ForcedChunksSaveData;
|
||||||
import net.minecraft.world.WorldSettings;
|
import net.minecraft.world.WorldSettings;
|
||||||
import net.minecraft.world.WorldType;
|
import net.minecraft.world.WorldType;
|
||||||
import net.minecraft.world.chunk.listener.IChunkStatusListener;
|
import net.minecraft.world.chunk.listener.IChunkStatusListener;
|
||||||
import net.minecraft.world.chunk.listener.IChunkStatusListenerFactory;
|
import net.minecraft.world.chunk.listener.IChunkStatusListenerFactory;
|
||||||
|
import net.minecraft.world.dimension.DimensionType;
|
||||||
|
import net.minecraft.world.server.ServerChunkProvider;
|
||||||
import net.minecraft.world.server.ServerWorld;
|
import net.minecraft.world.server.ServerWorld;
|
||||||
|
import net.minecraft.world.server.TicketType;
|
||||||
import net.minecraft.world.storage.SaveHandler;
|
import net.minecraft.world.storage.SaveHandler;
|
||||||
import net.minecraft.world.storage.WorldInfo;
|
import net.minecraft.world.storage.WorldInfo;
|
||||||
import net.minecraftforge.fml.StartupQuery;
|
import net.minecraftforge.fml.StartupQuery;
|
||||||
|
@ -53,6 +64,7 @@ import org.spongepowered.asm.mixin.Shadow;
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
|
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
@ -94,12 +106,16 @@ public abstract class MinecraftServerMixin extends RecursiveEventLoop<TickDelaye
|
||||||
@Shadow protected abstract void stopServer();
|
@Shadow protected abstract void stopServer();
|
||||||
@Shadow protected abstract void systemExitNow();
|
@Shadow protected abstract void systemExitNow();
|
||||||
@Shadow public abstract Commands getCommandManager();
|
@Shadow public abstract Commands getCommandManager();
|
||||||
|
@Shadow protected abstract void applyDebugWorldInfo(WorldInfo worldInfoIn);
|
||||||
|
@Shadow protected abstract void setUserMessage(ITextComponent userMessageIn);
|
||||||
|
@Shadow public abstract ServerWorld getWorld(DimensionType dimension);
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
|
|
||||||
public MinecraftServerMixin(String name) {
|
public MinecraftServerMixin(String name) {
|
||||||
super(name);
|
super(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean forceTicks;
|
||||||
public CraftServer server;
|
public CraftServer server;
|
||||||
public OptionSet options;
|
public OptionSet options;
|
||||||
public ConsoleCommandSender console;
|
public ConsoleCommandSender console;
|
||||||
|
@ -199,7 +215,7 @@ public abstract class MinecraftServerMixin extends RecursiveEventLoop<TickDelaye
|
||||||
ServerLifecycleHooks.expectServerStopped(); // has to come before finalTick to avoid race conditions
|
ServerLifecycleHooks.expectServerStopped(); // has to come before finalTick to avoid race conditions
|
||||||
} else {
|
} else {
|
||||||
ServerLifecycleHooks.expectServerStopped(); // has to come before finalTick to avoid race conditions
|
ServerLifecycleHooks.expectServerStopped(); // has to come before finalTick to avoid race conditions
|
||||||
this.finalTick((CrashReport) null);
|
this.finalTick(null);
|
||||||
}
|
}
|
||||||
} catch (StartupQuery.AbortedException e) {
|
} catch (StartupQuery.AbortedException e) {
|
||||||
// ignore silently
|
// ignore silently
|
||||||
|
@ -215,7 +231,7 @@ public abstract class MinecraftServerMixin extends RecursiveEventLoop<TickDelaye
|
||||||
|
|
||||||
File file1 = new File(new File(this.getDataDirectory(), "crash-reports"), "crash-" + (new SimpleDateFormat("yyyy-MM-dd_HH.mm.ss")).format(new Date()) + "-server.txt");
|
File file1 = new File(new File(this.getDataDirectory(), "crash-reports"), "crash-" + (new SimpleDateFormat("yyyy-MM-dd_HH.mm.ss")).format(new Date()) + "-server.txt");
|
||||||
if (crashreport.saveToFile(file1)) {
|
if (crashreport.saveToFile(file1)) {
|
||||||
LOGGER.error("This crash report has been saved to: {}", (Object) file1.getAbsolutePath());
|
LOGGER.error("This crash report has been saved to: {}", file1.getAbsolutePath());
|
||||||
} else {
|
} else {
|
||||||
LOGGER.error("We were unable to save this crash report to disk.");
|
LOGGER.error("We were unable to save this crash report to disk.");
|
||||||
}
|
}
|
||||||
|
@ -265,17 +281,90 @@ public abstract class MinecraftServerMixin extends RecursiveEventLoop<TickDelaye
|
||||||
this.server.getPluginManager().callEvent(new ServerLoadEvent(ServerLoadEvent.LoadType.STARTUP));
|
this.server.getPluginManager().callEvent(new ServerLoadEvent(ServerLoadEvent.LoadType.STARTUP));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Inject(method = "loadWorlds", locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/server/MinecraftServer;func_213204_a(Lnet/minecraft/world/storage/DimensionSavedDataManager;)V"))
|
public void initWorld(ServerWorld serverWorld, WorldInfo worldInfo, WorldSettings worldSettings) {
|
||||||
private void arclight$worldInit(SaveHandler p_213194_1_, WorldInfo info, WorldSettings p_213194_3_, IChunkStatusListener p_213194_4_, CallbackInfo ci, ServerWorld serverWorld) {
|
serverWorld.getWorldBorder().copyFrom(worldInfo);
|
||||||
if (((CraftServer) Bukkit.getServer()).scoreboardManager == null) {
|
|
||||||
((CraftServer) Bukkit.getServer()).scoreboardManager = new CraftScoreboardManager((MinecraftServer) (Object) this, serverWorld.getScoreboard());
|
|
||||||
}
|
|
||||||
Bukkit.getPluginManager().callEvent(new WorldInitEvent(((WorldBridge) serverWorld).bridge$getWorld()));
|
|
||||||
if (((WorldBridge) serverWorld).bridge$getGenerator() != null) {
|
if (((WorldBridge) serverWorld).bridge$getGenerator() != null) {
|
||||||
((WorldBridge) serverWorld).bridge$getWorld().getPopulators().addAll(
|
((WorldBridge) serverWorld).bridge$getWorld().getPopulators().addAll(
|
||||||
((WorldBridge) serverWorld).bridge$getGenerator().getDefaultPopulators(
|
((WorldBridge) serverWorld).bridge$getGenerator().getDefaultPopulators(
|
||||||
((WorldBridge) serverWorld).bridge$getWorld()));
|
((WorldBridge) serverWorld).bridge$getWorld()));
|
||||||
}
|
}
|
||||||
|
if (!worldInfo.isInitialized()) {
|
||||||
|
try {
|
||||||
|
serverWorld.createSpawnPosition(worldSettings);
|
||||||
|
if (worldInfo.getGenerator() == WorldType.DEBUG_ALL_BLOCK_STATES) {
|
||||||
|
this.applyDebugWorldInfo(worldInfo);
|
||||||
|
}
|
||||||
|
worldInfo.setInitialized(true);
|
||||||
|
} catch (Throwable throwable) {
|
||||||
|
CrashReport crashreport = CrashReport.makeCrashReport(throwable, "Exception initializing level");
|
||||||
|
try {
|
||||||
|
serverWorld.fillCrashReport(crashreport);
|
||||||
|
} catch (Throwable ignored) {}
|
||||||
|
throw new ReportedException(crashreport);
|
||||||
|
}
|
||||||
|
worldInfo.setInitialized(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void loadSpawn(IChunkStatusListener listener, ServerWorld serverWorld) {
|
||||||
|
if (!((WorldBridge) serverWorld).bridge$getWorld().getKeepSpawnInMemory()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.setUserMessage(new TranslationTextComponent("menu.generatingTerrain"));
|
||||||
|
this.forceTicks = true;
|
||||||
|
LOGGER.info("Preparing start region for dimension '{}'/{}", serverWorld.getWorldInfo().getWorldName(), DimensionType.getKey(((DimensionTypeBridge) serverWorld.dimension.getType()).bridge$getType()));
|
||||||
|
BlockPos pos = serverWorld.getSpawnPoint();
|
||||||
|
listener.start(new ChunkPos(pos));
|
||||||
|
ServerChunkProvider chunkProvider = serverWorld.getChunkProvider();
|
||||||
|
chunkProvider.getLightManager().func_215598_a(500);
|
||||||
|
this.serverTime = Util.milliTime();
|
||||||
|
chunkProvider.registerTicket(TicketType.START, new ChunkPos(pos), 11, Unit.INSTANCE);
|
||||||
|
while (chunkProvider.getLoadedChunksCount() != 441) {
|
||||||
|
this.executeModerately();
|
||||||
|
}
|
||||||
|
this.executeModerately();
|
||||||
|
DimensionType type = serverWorld.dimension.getType();
|
||||||
|
ForcedChunksSaveData chunks = serverWorld.getSavedData().get(ForcedChunksSaveData::new, "chunks");
|
||||||
|
if (chunks != null) {
|
||||||
|
ServerWorld world = this.getWorld(type);
|
||||||
|
LongIterator iterator = chunks.getChunks().iterator();
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
long i = iterator.nextLong();
|
||||||
|
ChunkPos chunkPos = new ChunkPos(i);
|
||||||
|
world.getChunkProvider().forceChunk(chunkPos, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.executeModerately();
|
||||||
|
listener.stop();
|
||||||
|
chunkProvider.getLightManager().func_215598_a(5);
|
||||||
|
this.forceTicks = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void executeModerately() {
|
||||||
|
this.drainTasks();
|
||||||
|
java.util.concurrent.locks.LockSupport.parkNanos("executing tasks", 1000L);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Inject(method = "isAheadOfTime", cancellable = true, at = @At("HEAD"))
|
||||||
|
private void arclight$forceAheadOfTime(CallbackInfoReturnable<Boolean> cir) {
|
||||||
|
if (this.forceTicks) cir.setReturnValue(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Inject(method = "loadWorlds", locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/server/MinecraftServer;func_213204_a(Lnet/minecraft/world/storage/DimensionSavedDataManager;)V"))
|
||||||
|
private void arclight$worldInit(SaveHandler p_213194_1_, WorldInfo info, WorldSettings p_213194_3_, IChunkStatusListener p_213194_4_, CallbackInfo ci, ServerWorld serverWorld) {
|
||||||
|
if (((CraftServer) Bukkit.getServer()).scoreboardManager == null) {
|
||||||
|
((CraftServer) Bukkit.getServer()).scoreboardManager = new CraftScoreboardManager((MinecraftServer) (Object) this, serverWorld.getScoreboard());
|
||||||
|
}
|
||||||
|
if (((WorldBridge) serverWorld).bridge$getGenerator() != null) {
|
||||||
|
((WorldBridge) serverWorld).bridge$getWorld().getPopulators().addAll(
|
||||||
|
((WorldBridge) serverWorld).bridge$getGenerator().getDefaultPopulators(
|
||||||
|
((WorldBridge) serverWorld).bridge$getWorld()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Inject(method = "loadWorlds", locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", target = "Lnet/minecraft/server/management/PlayerList;func_212504_a(Lnet/minecraft/world/server/ServerWorld;)V"))
|
||||||
|
private void arclight$initEvent(SaveHandler saveHandlerIn, WorldInfo info, WorldSettings worldSettingsIn, IChunkStatusListener chunkStatusListenerIn, CallbackInfo ci, ServerWorld serverWorld) {
|
||||||
|
Bukkit.getPluginManager().callEvent(new WorldInitEvent(((WorldBridge) serverWorld).bridge$getWorld()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Inject(method = "updateTimeLightAndEntities", at = @At("HEAD"))
|
@Inject(method = "updateTimeLightAndEntities", at = @At("HEAD"))
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package io.izzel.arclight.common.mixin.core.world;
|
package io.izzel.arclight.common.mixin.core.world;
|
||||||
|
|
||||||
|
import io.izzel.arclight.api.ArclightVersion;
|
||||||
import io.izzel.arclight.common.bridge.world.WorldBridge;
|
import io.izzel.arclight.common.bridge.world.WorldBridge;
|
||||||
import io.izzel.arclight.common.bridge.world.border.WorldBorderBridge;
|
import io.izzel.arclight.common.bridge.world.border.WorldBorderBridge;
|
||||||
import io.izzel.arclight.common.mod.util.ArclightCaptures;
|
import io.izzel.arclight.common.mod.util.ArclightCaptures;
|
||||||
|
@ -76,8 +77,13 @@ public abstract class WorldMixin implements WorldBridge {
|
||||||
((WorldBorderBridge) this.worldBorder).bridge$setWorld((ServerWorld) (Object) this);
|
((WorldBorderBridge) this.worldBorder).bridge$setWorld((ServerWorld) (Object) this);
|
||||||
this.ticksPerAnimalSpawns = this.getServer().getTicksPerAnimalSpawns();
|
this.ticksPerAnimalSpawns = this.getServer().getTicksPerAnimalSpawns();
|
||||||
this.ticksPerMonsterSpawns = this.getServer().getTicksPerMonsterSpawns();
|
this.ticksPerMonsterSpawns = this.getServer().getTicksPerMonsterSpawns();
|
||||||
|
if (ArclightVersion.atLeast(ArclightVersion.v1_15)) {
|
||||||
this.ticksPerWaterSpawns = this.getServer().getTicksPerWaterSpawns();
|
this.ticksPerWaterSpawns = this.getServer().getTicksPerWaterSpawns();
|
||||||
this.ticksPerAmbientSpawns = this.getServer().getTicksPerAmbientSpawns();
|
this.ticksPerAmbientSpawns = this.getServer().getTicksPerAmbientSpawns();
|
||||||
|
} else {
|
||||||
|
this.ticksPerWaterSpawns = 1;
|
||||||
|
this.ticksPerAmbientSpawns = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -200,7 +206,7 @@ public abstract class WorldMixin implements WorldBridge {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CraftWorld bridge$getWorld() {
|
public CraftWorld bridge$getWorld() {
|
||||||
return this.world;
|
return this.getWorld();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -92,7 +92,7 @@ public abstract class ServerWorldMixin extends WorldMixin implements ServerWorld
|
||||||
throw new RuntimeException();
|
throw new RuntimeException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void arclight$constructor(MinecraftServer serverIn, Executor executor, SaveHandler saveHandler, WorldInfo worldInfo, DimensionType dimType, IProfiler profiler, IChunkStatusListener listener, org.bukkit.generator.ChunkGenerator gen, org.bukkit.World.Environment env) {
|
public void arclight$constructor(MinecraftServer serverIn, Executor executor, SaveHandler saveHandler, WorldInfo worldInfo, DimensionType dimType, IProfiler profiler, IChunkStatusListener listener, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen) {
|
||||||
arclight$constructor(serverIn, executor, saveHandler, worldInfo, dimType, profiler, listener);
|
arclight$constructor(serverIn, executor, saveHandler, worldInfo, dimType, profiler, listener);
|
||||||
this.generator = gen;
|
this.generator = gen;
|
||||||
this.environment = env;
|
this.environment = env;
|
||||||
|
|
|
@ -6,6 +6,9 @@ import net.minecraft.world.biome.IBiomeMagnifier;
|
||||||
import net.minecraft.world.dimension.Dimension;
|
import net.minecraft.world.dimension.Dimension;
|
||||||
import net.minecraft.world.dimension.DimensionType;
|
import net.minecraft.world.dimension.DimensionType;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||||
|
|
||||||
import java.util.function.BiFunction;
|
import java.util.function.BiFunction;
|
||||||
|
|
||||||
|
@ -36,4 +39,11 @@ public class DimensionTypeMixin_1_15 implements DimensionTypeBridge {
|
||||||
public DimensionType bridge$getType() {
|
public DimensionType bridge$getType() {
|
||||||
return getType();
|
return getType();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Inject(method = "isVanilla", remap = false, cancellable = true, at = @At("HEAD"))
|
||||||
|
private void arclight$vanillaCheck(CallbackInfoReturnable<Boolean> cir) {
|
||||||
|
if (this.type != null) {
|
||||||
|
cir.setReturnValue(this.type.isVanilla());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,7 +56,7 @@ public class BukkitRegistry {
|
||||||
private static void loadEntities() {
|
private static void loadEntities() {
|
||||||
int origin = EntityType.values().length;
|
int origin = EntityType.values().length;
|
||||||
int i = origin;
|
int i = origin;
|
||||||
List<EntityType> newTypes = new ArrayList<>(ForgeRegistries.ENTITIES.getEntries().size() - origin);
|
List<EntityType> newTypes = new ArrayList<>(ForgeRegistries.ENTITIES.getEntries().size() - origin + 1); // UNKNOWN
|
||||||
for (Map.Entry<ResourceLocation, net.minecraft.entity.EntityType<?>> entry : ForgeRegistries.ENTITIES.getEntries()) {
|
for (Map.Entry<ResourceLocation, net.minecraft.entity.EntityType<?>> entry : ForgeRegistries.ENTITIES.getEntries()) {
|
||||||
ResourceLocation location = entry.getKey();
|
ResourceLocation location = entry.getKey();
|
||||||
net.minecraft.entity.EntityType<?> type = entry.getValue();
|
net.minecraft.entity.EntityType<?> type = entry.getValue();
|
||||||
|
|
|
@ -5,6 +5,9 @@ import net.minecraft.world.World;
|
||||||
import net.minecraft.world.dimension.Dimension;
|
import net.minecraft.world.dimension.Dimension;
|
||||||
import net.minecraft.world.dimension.DimensionType;
|
import net.minecraft.world.dimension.DimensionType;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||||
|
|
||||||
import java.util.function.BiFunction;
|
import java.util.function.BiFunction;
|
||||||
|
|
||||||
|
@ -35,4 +38,11 @@ public class DimensionTypeMixin_1_14 implements DimensionTypeBridge {
|
||||||
public DimensionType bridge$getType() {
|
public DimensionType bridge$getType() {
|
||||||
return getType();
|
return getType();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Inject(method = "isVanilla", remap = false, cancellable = true, at = @At("HEAD"))
|
||||||
|
private void arclight$vanillaCheck(CallbackInfoReturnable<Boolean> cir) {
|
||||||
|
if (this.type != null) {
|
||||||
|
cir.setReturnValue(this.type.isVanilla());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user