Search in sources :

Example 16 with Tuple

use of org.spongepowered.api.util.Tuple in project SpongeCommon by SpongePowered.

the class FilterGenerator method generateClass.

public byte[] generateClass(String name, final ListenerClassVisitor.DiscoveredMethod method) throws ClassNotFoundException {
    name = name.replace('.', '/');
    final ListenerClassVisitor.ListenerParameter[] parameters = method.parameterTypes();
    SubtypeFilterDelegate sfilter = null;
    final List<FilterDelegate> additional = new ArrayList<>();
    boolean cancellation = false;
    for (final ListenerClassVisitor.ListenerAnnotation anno : method.annotations()) {
        final Annotation annotation;
        try {
            annotation = anno.annotation();
        } catch (final AnnotationFormatException e) {
            throw new ClassNotFoundException("Failed to load annotation", e);
        }
        final Object obj = FilterGenerator.filterFromAnnotation(method.classByLoader(anno.type().getClassName()));
        if (obj == null) {
            continue;
        }
        if (obj instanceof SubtypeFilter) {
            if (sfilter != null) {
                throw new IllegalStateException("Cannot have both @Include and @Exclude annotations present at once");
            }
            sfilter = ((SubtypeFilter) obj).getDelegate(annotation);
        } else if (obj instanceof EventTypeFilter) {
            final EventTypeFilter etf = (EventTypeFilter) obj;
            additional.add(etf.getDelegate(annotation));
            if (etf == EventTypeFilter.CANCELLATION) {
                cancellation = true;
            }
        }
    }
    if (!cancellation && Cancellable.class.isAssignableFrom(parameters[0].clazz())) {
        additional.add(new CancellationEventFilterDelegate(Tristate.FALSE));
    }
    // we know there are no filters, skip generating a class
    if (additional.isEmpty() && sfilter == null && parameters.length == 1) {
        return null;
    }
    final ClassWriter cw = new LoaderClassWriter(method.declaringClass().getClassLoader(), ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
    MethodVisitor mv;
    cw.visit(V1_6, ACC_PUBLIC + ACC_FINAL + ACC_SUPER, name, null, "java/lang/Object", new String[] { Type.getInternalName(EventFilter.class) });
    if (sfilter != null) {
        sfilter.createFields(cw);
    }
    {
        mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
        mv.visitCode();
        mv.visitVarInsn(ALOAD, 0);
        mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
        if (sfilter != null) {
            sfilter.writeCtor(name, cw, mv);
        }
        mv.visitInsn(RETURN);
        mv.visitMaxs(0, 0);
        mv.visitEnd();
    }
    {
        mv = cw.visitMethod(ACC_PUBLIC, "filter", "(" + Type.getDescriptor(Event.class) + ")[Ljava/lang/Object;", null, null);
        mv.visitCode();
        // index of the next available local variable
        int local = 2;
        if (sfilter != null) {
            local = sfilter.write(name, cw, mv, method, local);
        }
        for (final FilterDelegate eventFilter : additional) {
            local = eventFilter.write(name, cw, mv, method, local);
        }
        // local var indices of the parameters values
        final int[] plocals = new int[parameters.length - 1];
        for (int i = 1; i < parameters.length; i++) {
            final ListenerClassVisitor.ListenerParameter param = parameters[i];
            ParameterFilterSourceDelegate source = null;
            final List<ParameterFilterDelegate> paramFilters = new ArrayList<>();
            for (final ListenerClassVisitor.ListenerAnnotation anno : param.annotations()) {
                final Object obj = FilterGenerator.filterFromAnnotation(method.classByLoader(anno.type().getClassName()));
                if (obj == null) {
                    continue;
                }
                final Annotation annotation;
                try {
                    annotation = anno.annotation();
                } catch (AnnotationFormatException e) {
                    throw new ClassNotFoundException("Failed to load annotation", e);
                }
                if (obj instanceof ParameterSource) {
                    if (source != null) {
                        throw new IllegalStateException("Cannot have multiple parameter filter source annotations (for " + param.name() + ")");
                    }
                    source = ((ParameterSource) obj).getDelegate(annotation);
                } else if (obj instanceof ParameterFilter) {
                    paramFilters.add(((ParameterFilter) obj).getDelegate(annotation));
                }
            }
            if (source == null) {
                throw new IllegalStateException("Cannot have additional parameters filters without a source (for " + param.name() + ")");
            }
            if (source instanceof AllCauseFilterSourceDelegate && !paramFilters.isEmpty()) {
                // TODO until better handling for filtering arrays is added
                throw new IllegalStateException("Cannot have additional parameters filters without an array source (for " + param.name() + ")");
            }
            final Tuple<Integer, Integer> localState = source.write(cw, mv, method, i, local, plocals, parameters);
            local = localState.first();
            plocals[i - 1] = localState.second();
            for (final ParameterFilterDelegate paramFilter : paramFilters) {
                paramFilter.write(cw, mv, param, plocals[i - 1]);
            }
        }
        // create the return array
        if (parameters.length == 1) {
            mv.visitInsn(ICONST_1);
        } else {
            mv.visitIntInsn(BIPUSH, parameters.length);
        }
        mv.visitTypeInsn(ANEWARRAY, "java/lang/Object");
        // load the event into the array
        mv.visitInsn(DUP);
        mv.visitInsn(ICONST_0);
        mv.visitVarInsn(ALOAD, 1);
        mv.visitInsn(AASTORE);
        // load all the params into the array
        for (int i = 1; i < parameters.length; i++) {
            mv.visitInsn(DUP);
            mv.visitIntInsn(BIPUSH, i);
            final Type paramType = parameters[i].type();
            mv.visitVarInsn(paramType.getOpcode(ILOAD), plocals[i - 1]);
            GeneratorUtils.visitBoxingMethod(mv, paramType);
            mv.visitInsn(AASTORE);
        }
        mv.visitInsn(ARETURN);
        mv.visitMaxs(0, 0);
        mv.visitEnd();
    }
    cw.visitEnd();
    final byte[] data = cw.toByteArray();
    if (FilterGenerator.FILTER_DEBUG) {
        final File outDir = new File(".sponge.debug.out");
        final File outFile = new File(outDir, name + ".class");
        if (!outFile.getParentFile().exists()) {
            outFile.getParentFile().mkdirs();
        }
        try (final FileOutputStream out = new FileOutputStream(outFile)) {
            out.write(data);
        } catch (final IOException ignored) {
            ignored.printStackTrace();
        }
    }
    return data;
}
Also used : CancellationEventFilterDelegate(org.spongepowered.common.event.filter.delegate.CancellationEventFilterDelegate) Cancellable(org.spongepowered.api.event.Cancellable) ArrayList(java.util.ArrayList) ParameterFilterDelegate(org.spongepowered.common.event.filter.delegate.ParameterFilterDelegate) MethodVisitor(org.objectweb.asm.MethodVisitor) ListenerClassVisitor(org.spongepowered.common.event.manager.ListenerClassVisitor) AnnotationFormatException(io.leangen.geantyref.AnnotationFormatException) List(java.util.List) ArrayList(java.util.ArrayList) LoaderClassWriter(org.spongepowered.common.event.gen.LoaderClassWriter) SubtypeFilterDelegate(org.spongepowered.common.event.filter.delegate.SubtypeFilterDelegate) SupportsDataFilterDelegate(org.spongepowered.common.event.filter.delegate.SupportsDataFilterDelegate) IncludeSubtypeFilterDelegate(org.spongepowered.common.event.filter.delegate.IncludeSubtypeFilterDelegate) FilterDelegate(org.spongepowered.common.event.filter.delegate.FilterDelegate) ParameterFilterDelegate(org.spongepowered.common.event.filter.delegate.ParameterFilterDelegate) HasDataFilterDelegate(org.spongepowered.common.event.filter.delegate.HasDataFilterDelegate) ExcludeSubtypeFilterDelegate(org.spongepowered.common.event.filter.delegate.ExcludeSubtypeFilterDelegate) CancellationEventFilterDelegate(org.spongepowered.common.event.filter.delegate.CancellationEventFilterDelegate) ParameterFilterSourceDelegate(org.spongepowered.common.event.filter.delegate.ParameterFilterSourceDelegate) AllCauseFilterSourceDelegate(org.spongepowered.common.event.filter.delegate.AllCauseFilterSourceDelegate) IOException(java.io.IOException) Annotation(java.lang.annotation.Annotation) LoaderClassWriter(org.spongepowered.common.event.gen.LoaderClassWriter) ClassWriter(org.objectweb.asm.ClassWriter) SubtypeFilterDelegate(org.spongepowered.common.event.filter.delegate.SubtypeFilterDelegate) IncludeSubtypeFilterDelegate(org.spongepowered.common.event.filter.delegate.IncludeSubtypeFilterDelegate) ExcludeSubtypeFilterDelegate(org.spongepowered.common.event.filter.delegate.ExcludeSubtypeFilterDelegate) Type(org.objectweb.asm.Type) FileOutputStream(java.io.FileOutputStream) Event(org.spongepowered.api.event.Event) File(java.io.File) Tuple(org.spongepowered.api.util.Tuple)

Example 17 with Tuple

use of org.spongepowered.api.util.Tuple in project SpongeCommon by SpongePowered.

the class ResolutionResult method printErrorsIfAny.

public void printErrorsIfAny(final Map<PluginCandidate<T>, String> failedInstance, final Map<PluginCandidate<T>, String> consequentialFailedInstance, final Logger logger) {
    final int noOfFailures = this.numberOfFailures() + failedInstance.size() + consequentialFailedInstance.size();
    if (noOfFailures == 0) {
        return;
    }
    final PrettyPrinter errorPrinter = new PrettyPrinter(120);
    errorPrinter.add("SPONGE PLUGINS FAILED TO LOAD").centre().hr().addWrapped("%d plugin(s) have unfulfilled or cyclic dependencies or failed to load. Your game will continue to load without" + " these plugins.", noOfFailures);
    if (!this.duplicateIds.isEmpty()) {
        errorPrinter.add();
        errorPrinter.add("The following plugins IDs were duplicated - some plugins will not have been loaded:");
        for (final String id : this.duplicateIds) {
            errorPrinter.add(" * %s", id);
        }
    }
    if (!this.missingDependencies.isEmpty()) {
        errorPrinter.add();
        errorPrinter.add("The following plugins are missing dependencies:");
        for (final Map.Entry<PluginCandidate<T>, Collection<String>> entry : this.missingDependencies.entrySet()) {
            errorPrinter.add(" * %s requires [ %s ]", entry.getKey().metadata().id(), String.join(", ", entry.getValue()));
        }
    }
    if (!this.versionMismatch.isEmpty()) {
        errorPrinter.add();
        errorPrinter.add("The following plugins require different version(s) of dependencies you have installed:");
        for (final Map.Entry<PluginCandidate<T>, Collection<Tuple<String, PluginCandidate<T>>>> entry : this.versionMismatch.entrySet()) {
            final PluginCandidate<T> candidate = entry.getKey();
            final Collection<Tuple<String, PluginCandidate<T>>> mismatchedDeps = entry.getValue();
            final String errorString = mismatchedDeps.stream().map(x -> String.format("%s version %s (currently version %s)", x.second().metadata().id(), x.first(), x.second().metadata().version())).collect(Collectors.joining(", "));
            errorPrinter.add(" * %s requires [ %s ]", candidate.metadata().id(), errorString);
        }
    }
    if (!this.cyclicDependency.isEmpty()) {
        errorPrinter.add();
        errorPrinter.add("The following plugins were found to have cyclic dependencies:");
        for (final Map.Entry<PluginCandidate<T>, Collection<PluginCandidate<T>>> node : this.cyclicDependency.entrySet()) {
            errorPrinter.add(" * %s has dependency cycle [ ... -> %s -> ... ]", node.getKey().metadata().id(), node.getValue().stream().map(x -> x.metadata().id()).collect(Collectors.joining(" -> ")));
        }
    }
    if (!failedInstance.isEmpty()) {
        errorPrinter.add();
        errorPrinter.add("The following plugins threw exceptions when being created (report these to the plugin authors):");
        for (final Map.Entry<PluginCandidate<T>, String> node : failedInstance.entrySet()) {
            errorPrinter.add(" * %s with the error message \"%s\"", node.getKey().metadata().id(), node.getValue());
        }
    }
    if (!this.cascadedFailure.isEmpty() || !consequentialFailedInstance.isEmpty()) {
        final Map<PluginCandidate<T>, String> mergedFailures = new HashMap<>(consequentialFailedInstance);
        for (final Map.Entry<PluginCandidate<T>, Collection<PluginCandidate<T>>> entry : this.cascadedFailure.entrySet()) {
            final String error = entry.getValue().stream().map(x -> x.metadata().id()).collect(Collectors.joining(", "));
            mergedFailures.merge(entry.getKey(), error, (old, incoming) -> old + ", " + incoming);
        }
        errorPrinter.add();
        errorPrinter.add("The following plugins are not loading because they depend on plugins that will not load:");
        for (final Map.Entry<PluginCandidate<T>, String> node : mergedFailures.entrySet()) {
            errorPrinter.add(" * %s depends on [ %s ]", node.getKey().metadata().id(), // so we just list all the plugins that failed
            node.getValue());
        }
    }
    errorPrinter.add().hr().addWrapped("DO NOT REPORT THIS TO SPONGE. These errors are not Sponge errors, they are plugin loading errors. Seek " + "support from the authors of the plugins listed above if you need help getting these plugins to load.").add();
    errorPrinter.addWrapped("Your game will continue to start without the %d plugins listed above. Other plugins will continue to load, " + "however you may wish to stop your game and fix these issues. For any missing dependencies, you " + "may be able to find them at https://ore.spongepowered.org/. For any plugins that have cyclic dependencies or threw " + "exceptions, it is likely a bug in the plugin.", noOfFailures);
    errorPrinter.log(logger, Level.ERROR);
}
Also used : HashSet(java.util.HashSet) Logger(org.apache.logging.log4j.Logger) PluginCandidate(org.spongepowered.plugin.PluginCandidate) Collection(java.util.Collection) Map(java.util.Map) Level(org.apache.logging.log4j.Level) PrettyPrinter(org.spongepowered.common.util.PrettyPrinter) HashMap(java.util.HashMap) Tuple(org.spongepowered.api.util.Tuple) PluginResource(org.spongepowered.plugin.PluginResource) Collectors(java.util.stream.Collectors) LinkedHashSet(java.util.LinkedHashSet) HashMap(java.util.HashMap) PluginCandidate(org.spongepowered.plugin.PluginCandidate) PrettyPrinter(org.spongepowered.common.util.PrettyPrinter) Collection(java.util.Collection) Map(java.util.Map) HashMap(java.util.HashMap) Tuple(org.spongepowered.api.util.Tuple)

Example 18 with Tuple

use of org.spongepowered.api.util.Tuple in project LanternServer by LanternPowered.

the class LanternPlayerAdvancements method createCriteria.

static Tuple<List<AdvancementCriterion>, String[][]> createCriteria(AdvancementCriterion criterion) {
    final List<AdvancementCriterion> criteria = new ArrayList<>();
    final List<String[]> names = new ArrayList<>();
    if (criterion instanceof AndCriterion) {
        for (AdvancementCriterion child : ((AndCriterion) criterion).getCriteria()) {
            if (child instanceof LanternScoreCriterion) {
                for (String id : ((LanternScoreCriterion) child).getIds()) {
                    names.add(new String[] { id });
                }
            } else {
                names.add(new String[] { child.getName() });
            }
            criteria.add(child);
        }
    } else {
        if (criterion instanceof LanternScoreCriterion) {
            for (String id : ((LanternScoreCriterion) criterion).getIds()) {
                names.add(new String[] { id });
            }
        } else {
            names.add(new String[] { criterion.getName() });
        }
        criteria.add(criterion);
    }
    return new Tuple<>(criteria, names.toArray(new String[names.size()][]));
}
Also used : AdvancementCriterion(org.spongepowered.api.advancement.criteria.AdvancementCriterion) ArrayList(java.util.ArrayList) LanternScoreCriterion(org.lanternpowered.server.advancement.criteria.LanternScoreCriterion) AndCriterion(org.spongepowered.api.advancement.criteria.AndCriterion) Tuple(org.spongepowered.api.util.Tuple)

Example 19 with Tuple

use of org.spongepowered.api.util.Tuple in project LanternServer by LanternPowered.

the class LanternEntity method collectDamageFunctions.

protected void collectDamageFunctions(List<Tuple<DamageFunction, Consumer<DamageEntityEvent>>> damageFunctions) {
    // Absorption health modifier
    get(Keys.ABSORPTION).filter(value -> value > 0).ifPresent(value -> {
        final DoubleUnaryOperator function = d -> -(Math.max(d - Math.max(d - value, 0), 0));
        final DamageModifier modifier = DamageModifier.builder().cause(Cause.of(EventContext.empty(), this)).type(DamageModifierTypes.ABSORPTION).build();
        damageFunctions.add(new Tuple<>(new DamageFunction(modifier, function), event -> {
            final double mod = event.getDamage(modifier);
            offer(Keys.ABSORPTION, Math.max(get(Keys.ABSORPTION).get() + mod, 0));
        }));
    });
}
Also used : EventContextKeys(org.spongepowered.api.event.cause.EventContextKeys) Random(java.util.Random) DamageSource(org.spongepowered.api.event.cause.entity.damage.source.DamageSource) LanternTexts(org.lanternpowered.server.text.LanternTexts) DataQueries(org.lanternpowered.server.data.DataQueries) ValueCollection(org.lanternpowered.server.data.ValueCollection) EntitySnapshot(org.spongepowered.api.entity.EntitySnapshot) Preconditions.checkArgument(com.google.common.base.Preconditions.checkArgument) DataHelper(org.lanternpowered.server.data.DataHelper) DamageEntityEvent(org.spongepowered.api.event.entity.DamageEntityEvent) EntityEvent(org.lanternpowered.server.entity.event.EntityEvent) AdditionalContainerCollection(org.lanternpowered.server.data.AdditionalContainerCollection) Living(org.spongepowered.api.entity.living.Living) EnumSet(java.util.EnumSet) HealingSource(org.spongepowered.api.event.cause.entity.health.source.HealingSource) Location(org.spongepowered.api.world.Location) AbstractPropertyHolder(org.lanternpowered.server.data.property.AbstractPropertyHolder) MutableBoundedValue(org.spongepowered.api.data.value.mutable.MutableBoundedValue) Sponge(org.spongepowered.api.Sponge) DataContainer(org.spongepowered.api.data.DataContainer) DamageTypes(org.spongepowered.api.event.cause.entity.damage.DamageTypes) Tuple(org.spongepowered.api.util.Tuple) UUID(java.util.UUID) Collectors(java.util.stream.Collectors) LanternGame(org.lanternpowered.server.game.LanternGame) Preconditions.checkState(com.google.common.base.Preconditions.checkState) EntityTypeRegistryModule(org.lanternpowered.server.game.registry.type.entity.EntityTypeRegistryModule) Direction(org.spongepowered.api.util.Direction) Cause(org.spongepowered.api.event.cause.Cause) List(java.util.List) Transform(org.spongepowered.api.entity.Transform) World(org.spongepowered.api.world.World) IAdditionalDataHolder(org.lanternpowered.server.data.IAdditionalDataHolder) DataManipulator(org.spongepowered.api.data.manipulator.DataManipulator) RelativePositions(org.spongepowered.api.util.RelativePositions) Optional(java.util.Optional) EntityProtocolType(org.lanternpowered.server.network.entity.EntityProtocolType) EventContext(org.spongepowered.api.event.cause.EventContext) LanternKeys(org.lanternpowered.server.data.key.LanternKeys) Keys(org.spongepowered.api.data.key.Keys) DestructEntityEvent(org.spongepowered.api.event.entity.DestructEntityEvent) Vector3d(com.flowpowered.math.vector.Vector3d) DamageModifierTypes(org.spongepowered.api.event.cause.entity.damage.DamageModifierTypes) AABB(org.spongepowered.api.util.AABB) DamagedEntityEvent(org.lanternpowered.server.entity.event.DamagedEntityEvent) GameModes(org.spongepowered.api.entity.living.player.gamemode.GameModes) HealEntityEvent(org.spongepowered.api.event.entity.HealEntityEvent) DoubleUnaryOperator(java.util.function.DoubleUnaryOperator) ArrayList(java.util.ArrayList) CauseStack(org.lanternpowered.server.event.CauseStack) ImmutableList(com.google.common.collect.ImmutableList) Text(org.spongepowered.api.text.Text) Quaternions(org.lanternpowered.server.util.Quaternions) LanternWorld(org.lanternpowered.server.world.LanternWorld) FixedTranslation(org.spongepowered.api.text.translation.FixedTranslation) Nullable(javax.annotation.Nullable) Translation(org.spongepowered.api.text.translation.Translation) LanternEventContextKeys(org.lanternpowered.server.event.LanternEventContextKeys) DamageSources(org.spongepowered.api.event.cause.entity.damage.source.DamageSources) SpongeEventFactory(org.spongepowered.api.event.SpongeEventFactory) Preconditions.checkNotNull(com.google.common.base.Preconditions.checkNotNull) InvalidDataException(org.spongepowered.api.data.persistence.InvalidDataException) DataHolder(org.spongepowered.api.data.DataHolder) Entity(org.spongepowered.api.entity.Entity) Consumer(java.util.function.Consumer) DamageFunction(org.spongepowered.api.event.cause.entity.damage.DamageFunction) DamageModifier(org.spongepowered.api.event.cause.entity.damage.DamageModifier) DataView(org.spongepowered.api.data.DataView) Vector3i(com.flowpowered.math.vector.Vector3i) LanternPlayer(org.lanternpowered.server.entity.living.player.LanternPlayer) EntityType(org.spongepowered.api.entity.EntityType) MessageChannel(org.spongepowered.api.text.channel.MessageChannel) MessageEvent(org.spongepowered.api.event.message.MessageEvent) EntityArchetype(org.spongepowered.api.entity.EntityArchetype) DamageModifier(org.spongepowered.api.event.cause.entity.damage.DamageModifier) DamageFunction(org.spongepowered.api.event.cause.entity.damage.DamageFunction) DoubleUnaryOperator(java.util.function.DoubleUnaryOperator)

Example 20 with Tuple

use of org.spongepowered.api.util.Tuple in project LanternServer by LanternPowered.

the class LanternWorldManager method init.

/**
 * Initializes the root world and the dimension id map.
 */
@SuppressWarnings("SuspiciousMethodCalls")
public void init() throws IOException {
    final Path rootWorldDir = this.rootWorldDirectory.get();
    // The properties of the root world
    LanternWorldProperties rootWorldProperties = null;
    LevelData levelData;
    if (Files.exists(rootWorldDir)) {
        try {
            levelData = LanternWorldPropertiesIO.read(rootWorldDir, null, null);
            // Create a config
            try {
                final WorldConfigResult result = getOrCreateWorldConfig(levelData.worldName);
                rootWorldProperties = LanternWorldPropertiesIO.convert(levelData, result.config, result.newCreated);
                if (result.newCreated) {
                    result.config.save();
                }
            } catch (IOException e) {
                this.logger.error("Unable to read/write the root world config, please fix this issue before loading the world.", e);
                throw e;
            }
            // Already store the data
            addUpdatedWorldProperties(rootWorldProperties, this.rootWorldDirectory.get(), 0);
        } catch (FileNotFoundException e) {
        // We can ignore this exception, because this means
        // that we have to generate the world
        } catch (IOException e) {
            this.logger.error("Unable to load root world, please fix this issue before starting the server.", e);
            throw e;
        }
    }
    // Always use a new dimension map, we will scan for the worlds
    // through folders and the dimension ids will be generated or
    // refreshed if needed
    this.dimensionMap = new BitSet();
    LanternWorldProperties rootWorldProperties0 = rootWorldProperties;
    // Generate the root (default) world if missing
    if (rootWorldProperties0 == null) {
        final String name = "Overworld";
        rootWorldProperties0 = createWorld(WorldArchetype.builder().from(WorldArchetypes.OVERWORLD).generator(GeneratorTypes.OVERWORLD).build(name, name), "", 0);
    }
    // Get all the dimensions (worlds) that should be loaded
    final List<WorldLookupEntry> loadQueue = new ArrayList<>(1);
    // Add the root dimension
    loadQueue.add(this.worldByDimensionId.get(0));
    final Map<Integer, Tuple<Path, LevelData>> idToLevelData = new HashMap<>();
    final List<Tuple<Path, LevelData>> levelDataWithoutId = new ArrayList<>();
    if (rootWorldProperties != null) {
        for (Path path : Files.list(rootWorldDir).filter(Files::isDirectory).collect(Collectors.toList())) {
            if (Files.list(path).count() == 0 || this.ignoredDirectoryNames.contains(path.getFileName().toString().toLowerCase())) {
                continue;
            }
            try {
                try {
                    levelData = LanternWorldPropertiesIO.read(path, null, null);
                } catch (FileNotFoundException e) {
                    this.logger.info("Found a invalid world directory {} inside the root world directory, the level.dat file is missing", path.getFileName().toString());
                    continue;
                }
                final Integer dimensionId;
                if (path.getFileName().toString().equalsIgnoreCase("DIM1")) {
                    dimensionId = 1;
                } else if (path.getFileName().toString().equalsIgnoreCase("DIM-1")) {
                    dimensionId = -1;
                } else if (levelData.dimensionId != null && levelData.dimensionId >= MIN_CUSTOM_DIMENSION_ID) {
                    dimensionId = levelData.dimensionId;
                } else {
                    dimensionId = null;
                }
                final Tuple<Path, LevelData> tuple = Tuple.of(path, levelData);
                if (dimensionId == null || idToLevelData.containsValue(dimensionId)) {
                    levelDataWithoutId.add(tuple);
                } else {
                    idToLevelData.put(dimensionId, tuple);
                }
            } catch (Exception e) {
                this.logger.info("Unable to load the world in the directory {}", path.getFileName().toString());
            }
        }
    }
    // Generate a dimension id for all the worlds that need it
    for (Tuple<Path, LevelData> tuple : levelDataWithoutId) {
        idToLevelData.put(getNextFreeDimensionId(), tuple);
    }
    levelDataWithoutId.clear();
    // Load the world properties and config files for all the worlds
    for (Map.Entry<Integer, Tuple<Path, LevelData>> entry : idToLevelData.entrySet()) {
        levelData = entry.getValue().getSecond();
        final LanternWorldProperties worldProperties;
        try {
            final WorldConfigResult result = getOrCreateWorldConfig(levelData.worldName);
            worldProperties = LanternWorldPropertiesIO.convert(levelData, result.config, result.newCreated);
            if (result.newCreated) {
                result.config.save();
            }
        } catch (IOException e) {
            this.logger.error("Unable to read/write the world config, please fix this issue before loading the world.", e);
            throw e;
        }
        // Store the world properties
        final WorldLookupEntry lookupEntry = addWorldProperties(worldProperties, entry.getValue().getFirst(), entry.getKey());
        // Check if it should be loaded on startup
        if (worldProperties.loadOnStartup()) {
            loadQueue.add(lookupEntry);
        }
    }
    if (!this.worldByDimensionId.containsKey(-1)) {
        final String name = "Nether";
        if (createWorld(WorldArchetype.builder().from(WorldArchetypes.THE_NETHER).generator(GeneratorTypes.NETHER).build(name, name), "DIM-1", -1).loadOnStartup()) {
            loadQueue.add(this.worldByDimensionId.get(-1));
        }
    }
    // The end
    if (!this.worldByDimensionId.containsKey(1)) {
        final String name = "TheEnd";
        if (createWorld(WorldArchetype.builder().from(WorldArchetypes.THE_END).generator(GeneratorTypes.THE_END).build(name, name), "DIM1", 1).loadOnStartup()) {
            loadQueue.add(this.worldByDimensionId.get(1));
        }
    }
    // The root world must be enabled
    rootWorldProperties0.setEnabled(true);
    // Load all the worlds
    loadQueue.forEach(this::loadWorld);
}
Also used : Path(java.nio.file.Path) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) HashMap(java.util.HashMap) FileNotFoundException(java.io.FileNotFoundException) BitSet(java.util.BitSet) ArrayList(java.util.ArrayList) IOException(java.io.IOException) FileNotFoundException(java.io.FileNotFoundException) RejectedExecutionException(java.util.concurrent.RejectedExecutionException) IOException(java.io.IOException) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) LevelData(org.lanternpowered.server.world.LanternWorldPropertiesIO.LevelData) Map(java.util.Map) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) HashMap(java.util.HashMap) Tuple(org.spongepowered.api.util.Tuple)

Aggregations

Tuple (org.spongepowered.api.util.Tuple)23 List (java.util.List)9 Map (java.util.Map)8 ArrayList (java.util.ArrayList)7 Optional (java.util.Optional)7 Type (org.objectweb.asm.Type)7 IOException (java.io.IOException)6 Collectors (java.util.stream.Collectors)6 Text (org.spongepowered.api.text.Text)5 Vector3d (com.flowpowered.math.vector.Vector3d)3 Nucleus (io.github.nucleuspowered.nucleus.Nucleus)3 HashMap (java.util.HashMap)3 Set (java.util.Set)3 Label (org.objectweb.asm.Label)3 Lists (com.google.common.collect.Lists)2 Maps (com.google.common.collect.Maps)2 TypeToken (com.google.common.reflect.TypeToken)2 Util (io.github.nucleuspowered.nucleus.Util)2 Reloadable (io.github.nucleuspowered.nucleus.internal.interfaces.Reloadable)2 File (java.io.File)2