minecraft-src/net/minecraft/server/Bootstrap.java
2025-07-04 03:15:13 +03:00

154 lines
5.4 KiB
Java

package net.minecraft.server;
import com.mojang.logging.LogUtils;
import java.io.PrintStream;
import java.time.Duration;
import java.time.Instant;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Function;
import java.util.function.Supplier;
import net.minecraft.SharedConstants;
import net.minecraft.SuppressForbidden;
import net.minecraft.commands.Commands;
import net.minecraft.commands.arguments.selector.options.EntitySelectorOptions;
import net.minecraft.core.cauldron.CauldronInteraction;
import net.minecraft.core.dispenser.DispenseItemBehavior;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.locale.Language;
import net.minecraft.world.effect.MobEffect;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.ai.attributes.Attribute;
import net.minecraft.world.entity.ai.attributes.DefaultAttributes;
import net.minecraft.world.flag.FeatureFlags;
import net.minecraft.world.item.CreativeModeTabs;
import net.minecraft.world.item.Item;
import net.minecraft.world.level.GameRules;
import net.minecraft.world.level.GameRules.GameRuleTypeVisitor;
import net.minecraft.world.level.GameRules.Key;
import net.minecraft.world.level.GameRules.Type;
import net.minecraft.world.level.GameRules.Value;
import net.minecraft.world.level.block.ComposterBlock;
import net.minecraft.world.level.block.FireBlock;
import net.minecraft.world.level.block.state.BlockBehaviour;
import org.slf4j.Logger;
@SuppressForbidden(
reason = "System.out setup"
)
public class Bootstrap {
public static final PrintStream STDOUT = System.out;
/**
* Whether the blocks, items, etc have already been registered
*/
private static volatile boolean isBootstrapped;
private static final Logger LOGGER = LogUtils.getLogger();
public static final AtomicLong bootstrapDuration = new AtomicLong(-1L);
/**
* Registers blocks, items, stats, etc.
*/
public static void bootStrap() {
if (!isBootstrapped) {
isBootstrapped = true;
Instant instant = Instant.now();
if (BuiltInRegistries.REGISTRY.keySet().isEmpty()) {
throw new IllegalStateException("Unable to load registries");
} else {
FireBlock.bootStrap();
ComposterBlock.bootStrap();
if (EntityType.getKey(EntityType.PLAYER) == null) {
throw new IllegalStateException("Failed loading EntityTypes");
} else {
EntitySelectorOptions.bootStrap();
DispenseItemBehavior.bootStrap();
CauldronInteraction.bootStrap();
BuiltInRegistries.bootStrap();
CreativeModeTabs.validate();
wrapStreams();
bootstrapDuration.set(Duration.between(instant, Instant.now()).toMillis());
}
}
}
}
private static <T> void checkTranslations(Iterable<T> objects, Function<T, String> objectToKeyFunction, Set<String> translationSet) {
Language language = Language.getInstance();
objects.forEach(object -> {
String string = (String)objectToKeyFunction.apply(object);
if (!language.has(string)) {
translationSet.add(string);
}
});
}
private static void checkGameruleTranslations(Set<String> translations) {
final Language language = Language.getInstance();
GameRules gameRules = new GameRules(FeatureFlags.REGISTRY.allFlags());
gameRules.visitGameRuleTypes(new GameRuleTypeVisitor() {
@Override
public <T extends Value<T>> void visit(Key<T> key, Type<T> type) {
if (!language.has(key.getDescriptionId())) {
translations.add(key.getId());
}
}
});
}
public static Set<String> getMissingTranslations() {
Set<String> set = new TreeSet();
checkTranslations(BuiltInRegistries.ATTRIBUTE, Attribute::getDescriptionId, set);
checkTranslations(BuiltInRegistries.ENTITY_TYPE, EntityType::getDescriptionId, set);
checkTranslations(BuiltInRegistries.MOB_EFFECT, MobEffect::getDescriptionId, set);
checkTranslations(BuiltInRegistries.ITEM, Item::getDescriptionId, set);
checkTranslations(BuiltInRegistries.BLOCK, BlockBehaviour::getDescriptionId, set);
checkTranslations(BuiltInRegistries.CUSTOM_STAT, resourceLocation -> "stat." + resourceLocation.toString().replace(':', '.'), set);
checkGameruleTranslations(set);
return set;
}
public static void checkBootstrapCalled(Supplier<String> callSite) {
if (!isBootstrapped) {
throw createBootstrapException(callSite);
}
}
private static RuntimeException createBootstrapException(Supplier<String> callSite) {
try {
String string = (String)callSite.get();
return new IllegalArgumentException("Not bootstrapped (called from " + string + ")");
} catch (Exception var3) {
RuntimeException runtimeException = new IllegalArgumentException("Not bootstrapped (failed to resolve location)");
runtimeException.addSuppressed(var3);
return runtimeException;
}
}
public static void validate() {
checkBootstrapCalled(() -> "validate");
if (SharedConstants.IS_RUNNING_IN_IDE) {
getMissingTranslations().forEach(string -> LOGGER.error("Missing translations: {}", string));
Commands.validate();
}
DefaultAttributes.validate();
}
/**
* Redirect standard streams to logger.
*/
private static void wrapStreams() {
if (LOGGER.isDebugEnabled()) {
System.setErr(new DebugLoggedPrintStream("STDERR", System.err));
System.setOut(new DebugLoggedPrintStream("STDOUT", STDOUT));
} else {
System.setErr(new LoggedPrintStream("STDERR", System.err));
System.setOut(new LoggedPrintStream("STDOUT", STDOUT));
}
}
public static void realStdoutPrintln(String message) {
STDOUT.println(message);
}
}