Use the maven artifact code rather than our very outdated copy

This commit is contained in:
cpw 2018-10-03 22:47:07 -04:00
parent 4630741c7c
commit c6e7bbe18b
20 changed files with 121 additions and 1954 deletions

View file

@ -26,7 +26,6 @@ import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.capabilities.CapabilityManager; import net.minecraftforge.common.capabilities.CapabilityManager;
import net.minecraftforge.fml.language.IModInfo; import net.minecraftforge.fml.language.IModInfo;
import net.minecraftforge.fml.loading.DefaultModInfos; import net.minecraftforge.fml.loading.DefaultModInfos;
import net.minecraftforge.fml.loading.EarlyLoadingException;
import net.minecraftforge.fml.loading.FMLLoader; import net.minecraftforge.fml.loading.FMLLoader;
import net.minecraftforge.fml.loading.LoadingModList; import net.minecraftforge.fml.loading.LoadingModList;
import net.minecraftforge.fml.loading.moddiscovery.ModFile; import net.minecraftforge.fml.loading.moddiscovery.ModFile;
@ -36,7 +35,6 @@ import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;

View file

@ -19,7 +19,6 @@
package net.minecraftforge.fml; package net.minecraftforge.fml;
import com.google.common.collect.ObjectArrays;
import com.google.common.collect.Streams; import com.google.common.collect.Streams;
import net.minecraftforge.fml.language.IModInfo; import net.minecraftforge.fml.language.IModInfo;
import net.minecraftforge.fml.loading.EarlyLoadingException; import net.minecraftforge.fml.loading.EarlyLoadingException;

View file

@ -19,8 +19,8 @@
package net.minecraftforge.fml; package net.minecraftforge.fml;
import net.minecraftforge.fml.common.versioning.ComparableVersion;
import net.minecraftforge.fml.loading.moddiscovery.ModInfo; import net.minecraftforge.fml.loading.moddiscovery.ModInfo;
import org.apache.maven.artifact.versioning.ComparableVersion;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.net.URL; import java.net.URL;

View file

@ -43,13 +43,14 @@ import net.minecraftforge.fml.ModList;
import net.minecraftforge.fml.VersionChecker; import net.minecraftforge.fml.VersionChecker;
import net.minecraftforge.fml.client.ConfigGuiHandler; import net.minecraftforge.fml.client.ConfigGuiHandler;
import net.minecraftforge.fml.client.ResourcePackLoader; import net.minecraftforge.fml.client.ResourcePackLoader;
import net.minecraftforge.fml.common.versioning.ComparableVersion;
import net.minecraftforge.fml.language.IModInfo; import net.minecraftforge.fml.language.IModInfo;
import net.minecraftforge.fml.loading.MavenVersionAdapter;
import net.minecraftforge.fml.loading.StringUtils; import net.minecraftforge.fml.loading.StringUtils;
import net.minecraftforge.fml.loading.moddiscovery.ModInfo; import net.minecraftforge.fml.loading.moddiscovery.ModInfo;
import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.tuple.Pair;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.apache.maven.artifact.versioning.ComparableVersion;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.awt.Dimension; import java.awt.Dimension;
@ -290,7 +291,7 @@ public class GuiModList extends GuiScreen
for (ModInfo mod : mods) for (ModInfo mod : mods)
{ {
listWidth = Math.max(listWidth,getFontRenderer().getStringWidth(mod.getDisplayName()) + 10); listWidth = Math.max(listWidth,getFontRenderer().getStringWidth(mod.getDisplayName()) + 10);
listWidth = Math.max(listWidth,getFontRenderer().getStringWidth(mod.getVersion().getVersionString()) + 5); listWidth = Math.max(listWidth,getFontRenderer().getStringWidth(MavenVersionAdapter.artifactVersionToString(mod.getVersion())) + 5);
} }
listWidth = Math.min(listWidth, 150); listWidth = Math.min(listWidth, 150);
listWidth += listWidth % numButtons != 0 ? (numButtons - listWidth % numButtons) : 0; listWidth += listWidth % numButtons != 0 ? (numButtons - listWidth % numButtons) : 0;
@ -454,7 +455,7 @@ public class GuiModList extends GuiScreen
}).orElse(Pair.of(null, new Dimension(0, 0))); }).orElse(Pair.of(null, new Dimension(0, 0)));
lines.add(selectedMod.getDisplayName()); lines.add(selectedMod.getDisplayName());
lines.add(ForgeI18n.parseMessage("fml.menu.mods.info.version", selectedMod.getVersion().getVersionString())); lines.add(ForgeI18n.parseMessage("fml.menu.mods.info.version", MavenVersionAdapter.artifactVersionToString(selectedMod.getVersion())));
lines.add(ForgeI18n.parseMessage("fml.menu.mods.info.idstate", selectedMod.getModId(), ModList.get().getModContainerById(selectedMod.getModId()). lines.add(ForgeI18n.parseMessage("fml.menu.mods.info.idstate", selectedMod.getModId(), ModList.get().getModContainerById(selectedMod.getModId()).
map(ModContainer::getCurrentState).map(Object::toString).orElse("NONE"))); map(ModContainer::getCurrentState).map(Object::toString).orElse("NONE")));

View file

@ -1,52 +0,0 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2018.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.minecraftforge.fml.common.eventhandler;
import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.SubscriberExceptionHandler;
/**
* Event bus that allows exceptions thrown by the exception handler to propagate.
* TODO remove this in 1.13 and stop using the guava event bus
*/
public class FMLThrowingEventBus extends EventBus
{
public FMLThrowingEventBus(final SubscriberExceptionHandler exceptionHandler)
{
super((exception, context) -> {
try
{
exceptionHandler.handleException(exception, context);
}
catch (final Throwable t)
{
// this is a hack to break out of the catch statement in EventBus.handleSubscriberException
throw new RuntimeException()
{
@Override
public String toString()
{
throw t;
}
};
}
});
}
}

View file

@ -1,36 +0,0 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2018.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.minecraftforge.fml.common.versioning;
//I beleive this is a unique class except that it uses the same name so that ComparibleVersion can stay the same.
//Best reference I could find: https://github.com/apache/maven/blob/3501485ed2280e30ba74eb9f0e1c6422b68a3228/maven-artifact/src/main/java/org/apache/maven/artifact/versioning/ArtifactVersion.java
//This entire package *should* be removed and updated to normal maven-artifact library in 1.13.
public interface ArtifactVersion
extends Comparable<ArtifactVersion>
{
String getVersionString();
boolean containsVersion(ArtifactVersion source);
String getRangeString();
String getLabel();
}

View file

@ -1,488 +0,0 @@
/*
* Repackaged and some modifications done by Forge, see in-line comments.
*/
package net.minecraftforge.fml.common.versioning;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Locale;
import java.util.Properties;
import java.util.Stack;
/**
* Generic implementation of version comparison.
*
* <p>Features:
* <ul>
* <li>mixing of '<code>-</code>' (dash) and '<code>.</code>' (dot) separators,</li>
* <li>transition between characters and digits also constitutes a separator:
* <code>1.0alpha1 =&gt; [1, 0, alpha, 1]</code></li>
* <li>unlimited number of version components,</li>
* <li>version components in the text can be digits or strings,</li>
* <li>strings are checked for well-known qualifiers and the qualifier ordering is used for version ordering.
* Well-known qualifiers (case insensitive) are:<ul>
* <li><code>snapshot</code></li>
* <li><code>alpha</code> or <code>a</code></li>
* <li><code>beta</code> or <code>b</code></li>
* <li><code>milestone</code> or <code>m</code></li>
* <li><code>rc</code> or <code>cr</code></li>
* <li><code>(the empty string)</code> or <code>ga</code> or <code>final</code></li>
* <li><code>sp</code></li>
* </ul>
* Unknown qualifiers are considered after known qualifiers, with lexical order (always case insensitive),
* </li>
* <li>a dash usually precedes a qualifier, and is always less important than something preceded with a dot.</li>
* </ul></p>
*
* @see <a href="https://cwiki.apache.org/confluence/display/MAVENOLD/Versioning">"Versioning" on Maven Wiki</a>
* @author <a href="mailto:kenney@apache.org">Kenney Westerhof</a>
* @author <a href="mailto:hboutemy@apache.org">Hervé Boutemy</a>
*/
public class ComparableVersion
implements Comparable<ComparableVersion>
{
private String value;
private String canonical;
private ListItem items;
private interface Item
{
final int INTEGER_ITEM = 0;
final int STRING_ITEM = 1;
final int LIST_ITEM = 2;
int compareTo( Item item );
int getType();
boolean isNull();
}
/**
* Represents a numeric item in the version item list.
*/
private static class IntegerItem
implements Item
{
private static final BigInteger BigInteger_ZERO = new BigInteger( "0" );
private final BigInteger value;
public static final IntegerItem ZERO = new IntegerItem();
private IntegerItem()
{
this.value = BigInteger_ZERO;
}
public IntegerItem( String str )
{
this.value = new BigInteger( str );
}
@Override //Forge: Add @Override
public int getType()
{
return INTEGER_ITEM;
}
@Override //Forge: Add @Override
public boolean isNull()
{
return BigInteger_ZERO.equals( value );
}
@Override //Forge: Add @Override
public int compareTo( Item item )
{
if ( item == null )
{
return BigInteger_ZERO.equals( value ) ? 0 : 1; // 1.0 == 1, 1.1 > 1
}
switch ( item.getType() )
{
case INTEGER_ITEM:
return value.compareTo( ( (IntegerItem) item ).value );
case STRING_ITEM:
return 1; // 1.1 > 1-sp
case LIST_ITEM:
return 1; // 1.1 > 1-1
default:
throw new RuntimeException( "invalid item: " + item.getClass() );
}
}
@Override //Forge: Add @Override
public String toString()
{
return value.toString();
}
}
/**
* Represents a string in the version item list, usually a qualifier.
*/
private static class StringItem
implements Item
{
private static final String[] QUALIFIERS = { "alpha", "beta", "milestone", "rc", "snapshot", "", "sp" };
private static final List<String> _QUALIFIERS = Arrays.asList( QUALIFIERS );
private static final Properties ALIASES = new Properties();
static
{
ALIASES.put( "ga", "" );
ALIASES.put( "final", "" );
ALIASES.put( "cr", "rc" );
}
/**
* A comparable value for the empty-string qualifier. This one is used to determine if a given qualifier makes
* the version older than one without a qualifier, or more recent.
*/
private static final String RELEASE_VERSION_INDEX = String.valueOf( _QUALIFIERS.indexOf( "" ) );
private String value;
public StringItem( String value, boolean followedByDigit )
{
if ( followedByDigit && value.length() == 1 )
{
// a1 = alpha-1, b1 = beta-1, m1 = milestone-1
switch ( value.charAt( 0 ) )
{
case 'a':
value = "alpha";
break;
case 'b':
value = "beta";
break;
case 'm':
value = "milestone";
break;
}
}
this.value = ALIASES.getProperty( value , value );
}
@Override //Forge: Add @Override
public int getType()
{
return STRING_ITEM;
}
@Override //Forge: Add @Override
public boolean isNull()
{
return ( comparableQualifier( value ).compareTo( RELEASE_VERSION_INDEX ) == 0 );
}
/**
* Returns a comparable value for a qualifier.
*
* This method takes into account the ordering of known qualifiers then unknown qualifiers with lexical ordering.
*
* just returning an Integer with the index here is faster, but requires a lot of if/then/else to check for -1
* or QUALIFIERS.size and then resort to lexical ordering. Most comparisons are decided by the first character,
* so this is still fast. If more characters are needed then it requires a lexical sort anyway.
*
* @param qualifier
* @return an equivalent value that can be used with lexical comparison
*/
public static String comparableQualifier( String qualifier )
{
int i = _QUALIFIERS.indexOf( qualifier );
return i == -1 ? ( _QUALIFIERS.size() + "-" + qualifier ) : String.valueOf( i );
}
@Override //Forge: Add @Override
public int compareTo( Item item )
{
if ( item == null )
{
// 1-rc < 1, 1-ga > 1
return comparableQualifier( value ).compareTo( RELEASE_VERSION_INDEX );
}
switch ( item.getType() )
{
case INTEGER_ITEM:
return -1; // 1.any < 1.1 ?
case STRING_ITEM:
return comparableQualifier( value ).compareTo( comparableQualifier( ( (StringItem) item ).value ) );
case LIST_ITEM:
return -1; // 1.any < 1-1
default:
throw new RuntimeException( "invalid item: " + item.getClass() );
}
}
@Override //Forge: Add @Override
public String toString()
{
return value;
}
}
/**
* Represents a version list item. This class is used both for the global item list and for sub-lists (which start
* with '-(number)' in the version specification).
*/
private static class ListItem
extends ArrayList<Item>
implements Item
{
private static final long serialVersionUID = 1L; //Forge: added to quiet warnings.
@Override //Forge: Add @Override
public int getType()
{
return LIST_ITEM;
}
@Override //Forge: Add @Override
public boolean isNull()
{
return ( size() == 0 );
}
void normalize()
{
for( ListIterator<Item> iterator = listIterator( size() ); iterator.hasPrevious(); )
{
Item item = iterator.previous();
if ( item.isNull() )
{
iterator.remove(); // remove null trailing items: 0, "", empty list
}
else
{
break;
}
}
}
@Override //Forge: Add @Override
public int compareTo( Item item )
{
if ( item == null )
{
if ( size() == 0 )
{
return 0; // 1-0 = 1- (normalize) = 1
}
Item first = get( 0 );
return first.compareTo( null );
}
switch ( item.getType() )
{
case INTEGER_ITEM:
return -1; // 1-1 < 1.0.x
case STRING_ITEM:
return 1; // 1-1 > 1-sp
case LIST_ITEM:
Iterator<Item> left = iterator();
Iterator<Item> right = ( (ListItem) item ).iterator();
while ( left.hasNext() || right.hasNext() )
{
Item l = left.hasNext() ? left.next() : null;
Item r = right.hasNext() ? right.next() : null;
// if this is shorter, then invert the compare and mul with -1
int result = l == null ? -1 * r.compareTo( l ) : l.compareTo( r );
if ( result != 0 )
{
return result;
}
}
return 0;
default:
throw new RuntimeException( "invalid item: " + item.getClass() );
}
}
@Override //Forge: Add @Override
public String toString()
{
StringBuilder buffer = new StringBuilder( "(" );
for( Iterator<Item> iter = iterator(); iter.hasNext(); )
{
buffer.append( iter.next() );
if ( iter.hasNext() )
{
buffer.append( ',' );
}
}
buffer.append( ')' );
return buffer.toString();
}
}
public ComparableVersion( String version )
{
parseVersion( version );
}
public final void parseVersion( String version )
{
this.value = version;
items = new ListItem();
version = version.toLowerCase( Locale.ENGLISH );
ListItem list = items;
Stack<Item> stack = new Stack<Item>();
stack.push( list );
boolean isDigit = false;
int startIndex = 0;
for ( int i = 0; i < version.length(); i++ )
{
char c = version.charAt( i );
if ( c == '.' )
{
if ( i == startIndex )
{
list.add( IntegerItem.ZERO );
}
else
{
list.add( parseItem( isDigit, version.substring( startIndex, i ) ) );
}
startIndex = i + 1;
}
else if ( c == '-' )
{
if ( i == startIndex )
{
list.add( IntegerItem.ZERO );
}
else
{
list.add( parseItem( isDigit, version.substring( startIndex, i ) ) );
}
startIndex = i + 1;
if ( isDigit )
{
list.normalize(); // 1.0-* = 1-*
if ( ( i + 1 < version.length() ) && Character.isDigit( version.charAt( i + 1 ) ) )
{
// new ListItem only if previous were digits and new char is a digit,
// ie need to differentiate only 1.1 from 1-1
list.add( list = new ListItem() );
stack.push( list );
}
}
}
else if ( Character.isDigit( c ) )
{
if ( !isDigit && i > startIndex )
{
list.add( new StringItem( version.substring( startIndex, i ), true ) );
startIndex = i;
}
isDigit = true;
}
else
{
if ( isDigit && i > startIndex )
{
list.add( parseItem( true, version.substring( startIndex, i ) ) );
startIndex = i;
}
isDigit = false;
}
}
if ( version.length() > startIndex )
{
list.add( parseItem( isDigit, version.substring( startIndex ) ) );
}
while ( !stack.isEmpty() )
{
list = (ListItem) stack.pop();
list.normalize();
}
canonical = items.toString();
}
private static Item parseItem( boolean isDigit, String buf )
{
return isDigit ? new IntegerItem( buf ) : new StringItem( buf, false );
}
@Override //Forge: Add @Override
public int compareTo( ComparableVersion o )
{
return items.compareTo( o.items );
}
@Override //Forge: Add @Override
public String toString()
{
return value;
}
@Override //Forge: Add @Override
public boolean equals( Object o )
{
return ( o instanceof ComparableVersion ) && canonical.equals( ( (ComparableVersion) o ).canonical );
}
@Override //Forge: Add @Override
public int hashCode()
{
return canonical.hashCode();
}
}

View file

@ -1,116 +0,0 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2018.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.minecraftforge.fml.common.versioning;
public class DefaultArtifactVersion implements ArtifactVersion
{
private ComparableVersion comparableVersion;
private String label;
private boolean unbounded;
private VersionRange range;
public DefaultArtifactVersion(String versionNumber)
{
comparableVersion = new ComparableVersion(versionNumber);
range = VersionRange.createFromVersion(versionNumber, this);
}
public DefaultArtifactVersion(String label, VersionRange range)
{
this.label = label;
this.range = range;
}
public DefaultArtifactVersion(String label, String version)
{
this(version);
this.label = label;
}
public DefaultArtifactVersion(String string, boolean unbounded)
{
this.label = string;
this.unbounded = true;
}
@Override
public boolean equals(Object obj)
{
return ((DefaultArtifactVersion)obj).containsVersion(this);
}
@Override
public int compareTo(ArtifactVersion o)
{
return unbounded ? 0 : this.comparableVersion.compareTo(((DefaultArtifactVersion)o).comparableVersion);
}
@Override
public String getLabel()
{
return label;
}
@Override
public boolean containsVersion(ArtifactVersion source)
{
if (source.getLabel() != null && !source.getLabel().equals(getLabel()))
{
return false;
}
if (unbounded)
{
return true;
}
if (range != null)
{
return range.containsVersion(source);
}
else
{
return false;
}
}
@Override
public String getVersionString()
{
return comparableVersion == null ? "unknown" : comparableVersion.toString();
}
@Override
public String getRangeString()
{
return range == null ? "any" : range.toString();
}
@Override
public String toString()
{
if (label == null)
{
return getVersionString();
}
return label + (unbounded ? "" : "@" + range);
}
public VersionRange getRange()
{
return range;
}
}

View file

@ -1,38 +0,0 @@
/*
* Repackaged by Forge, otherwise unchangeed
*/
package net.minecraftforge.fml.common.versioning;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/**
* Occurs when a version is invalid.
*
* @author <a href="mailto:brett@apache.org">Brett Porter</a>
*/
public class InvalidVersionSpecificationException extends RuntimeException
{
private static final long serialVersionUID = 1L;
public InvalidVersionSpecificationException( String message )
{
super( message );
}
}

View file

@ -1,270 +0,0 @@
/*
* Repackaged and some modifications done by Forge, see in-line comments.
*/
package net.minecraftforge.fml.common.versioning;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import javax.annotation.Nullable;
import net.minecraft.client.resources.I18n;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
/**
* Describes a restriction in versioning.
*
* @author <a href="mailto:brett@apache.org">Brett Porter</a>
*/
public class Restriction
{
private final ArtifactVersion lowerBound;
private final boolean lowerBoundInclusive;
private final ArtifactVersion upperBound;
private final boolean upperBoundInclusive;
public static final Restriction EVERYTHING = new Restriction( null, false, null, false );
public Restriction( @Nullable ArtifactVersion lowerBound, boolean lowerBoundInclusive, @Nullable ArtifactVersion upperBound, //Forge: Added @Nullable
boolean upperBoundInclusive )
{
this.lowerBound = lowerBound;
this.lowerBoundInclusive = lowerBoundInclusive;
this.upperBound = upperBound;
this.upperBoundInclusive = upperBoundInclusive;
}
@Nullable //Forge: Added @Nullable
public ArtifactVersion getLowerBound()
{
return lowerBound;
}
public boolean isLowerBoundInclusive()
{
return lowerBoundInclusive;
}
@Nullable //Forge: Added @Nullable
public ArtifactVersion getUpperBound()
{
return upperBound;
}
public boolean isUpperBoundInclusive()
{
return upperBoundInclusive;
}
public boolean containsVersion( ArtifactVersion version )
{
if ( lowerBound != null )
{
int comparison = lowerBound.compareTo( version );
if ( ( comparison == 0 ) && !lowerBoundInclusive )
{
return false;
}
if ( comparison > 0 )
{
return false;
}
}
if ( upperBound != null )
{
int comparison = upperBound.compareTo( version );
if ( ( comparison == 0 ) && !upperBoundInclusive )
{
return false;
}
if ( comparison < 0 )
{
return false;
}
}
return true;
}
@Override
public int hashCode()
{
int result = 13;
if ( lowerBound == null )
{
result += 1;
}
else
{
result += lowerBound.hashCode();
}
result *= lowerBoundInclusive ? 1 : 2;
if ( upperBound == null )
{
result -= 3;
}
else
{
result -= upperBound.hashCode();
}
result *= upperBoundInclusive ? 2 : 3;
return result;
}
@Override
public boolean equals( Object other )
{
if ( this == other )
{
return true;
}
if ( !( other instanceof Restriction ) )
{
return false;
}
Restriction restriction = (Restriction) other;
if ( lowerBound != null )
{
if ( !lowerBound.equals( restriction.lowerBound ) )
{
return false;
}
}
else if ( restriction.lowerBound != null )
{
return false;
}
if ( lowerBoundInclusive != restriction.lowerBoundInclusive )
{
return false;
}
if ( upperBound != null )
{
if ( !upperBound.equals( restriction.upperBound ) )
{
return false;
}
}
else if ( restriction.upperBound != null )
{
return false;
}
if ( upperBoundInclusive != restriction.upperBoundInclusive )
{
return false;
}
return true;
}
@Override //Forge: Added @Override
public String toString()
{
StringBuilder buf = new StringBuilder();
buf.append( isLowerBoundInclusive() ? "[" : "(" );
if ( getLowerBound() != null )
{
buf.append( getLowerBound().toString() );
}
buf.append( "," );
if ( getUpperBound() != null )
{
buf.append( getUpperBound().toString() );
}
buf.append( isUpperBoundInclusive() ? "]" : ")" );
return buf.toString();
}
//Forge: Added toStringFriendly, uses Minecraft's localization engine to create user friendly localized message.
@OnlyIn(Dist.CLIENT)
public String toStringFriendly()
{
if ( getLowerBound() == null && getUpperBound() == null )
{
return I18n.format("fml.messages.version.restriction.any");
}
else if ( getLowerBound() != null && getUpperBound() != null )
{
if ( getLowerBound().getVersionString().equals(getUpperBound().getVersionString()) )
{
return getLowerBound().getVersionString();
}
else
{
if (isLowerBoundInclusive() && isUpperBoundInclusive())
{
return I18n.format("fml.messages.version.restriction.bounded.inclusive", getLowerBound(), getUpperBound());
}
else if (isLowerBoundInclusive())
{
return I18n.format("fml.messages.version.restriction.bounded.upperexclusive", getLowerBound(), getUpperBound());
}
else if (isUpperBoundInclusive())
{
return I18n.format("fml.messages.version.restriction.bounded.lowerexclusive", getLowerBound(), getUpperBound());
}
else
{
return I18n.format("fml.messages.version.restriction.bounded.exclusive", getLowerBound(), getUpperBound());
}
}
}
else if ( getLowerBound() != null )
{
if ( isLowerBoundInclusive() )
{
return I18n.format("fml.messages.version.restriction.lower.inclusive", getLowerBound());
}
else
{
return I18n.format("fml.messages.version.restriction.lower.exclusive", getLowerBound());
}
}
else
{
if ( isUpperBoundInclusive() )
{
return I18n.format("fml.messages.version.restriction.upper.inclusive", getUpperBound());
}
else
{
return I18n.format("fml.messages.version.restriction.upper.exclusive", getUpperBound());
}
}
}
}

View file

@ -1,610 +0,0 @@
/*
* Repackaged and some modifications done by Forge, see in-line comments.
*/
package net.minecraftforge.fml.common.versioning;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import com.google.common.base.Joiner; //Forge: Add Imports
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import javax.annotation.Nullable;
import com.google.common.base.Joiner;
/**
* Construct a version range from a specification.
*
* @author <a href="mailto:brett@apache.org">Brett Porter</a>
*/
public class VersionRange
{
private final ArtifactVersion recommendedVersion;
private final List<Restriction> restrictions;
private VersionRange( ArtifactVersion recommendedVersion,
List<Restriction> restrictions )
{
this.recommendedVersion = recommendedVersion;
this.restrictions = restrictions;
}
public ArtifactVersion getRecommendedVersion()
{
return recommendedVersion;
}
public List<Restriction> getRestrictions()
{
return restrictions;
}
public VersionRange cloneOf()
{
List<Restriction> copiedRestrictions = null;
if ( restrictions != null )
{
copiedRestrictions = new ArrayList<Restriction>();
if ( !restrictions.isEmpty() )
{
copiedRestrictions.addAll( restrictions );
}
}
return new VersionRange( recommendedVersion, copiedRestrictions );
}
//Forge: Added factory function
/**
* Factory method, for custom versioning schemes
* @param version version
* @param restrictions restriction list
* @return a new version range
*/
public static VersionRange newRange(ArtifactVersion version, List<Restriction> restrictions)
{
return new VersionRange(version, restrictions);
}
/**
* Create a version range from a string representation
* <p/>
* Some spec examples are
* <ul>
* <li><code>1.0</code> Version 1.0</li>
* <li><code>[1.0,2.0)</code> Versions 1.0 (included) to 2.0 (not included)</li>
* <li><code>[1.0,2.0]</code> Versions 1.0 to 2.0 (both included)</li>
* <li><code>[1.5,)</code> Versions 1.5 and higher</li>
* <li><code>(,1.0],[1.2,)</code> Versions up to 1.0 (included) and 1.2 or higher</li>
* </ul>
*
* @param spec string representation of a version or version range
* @return a new {@link VersionRange} object that represents the spec
* @throws InvalidVersionSpecificationException
*
*/
public static VersionRange createFromVersionSpec( @Nullable String spec ) //Forge: Added @Nullable
throws InvalidVersionSpecificationException
{
if ( spec == null )
{
return null;
}
List<Restriction> restrictions = new ArrayList<Restriction>();
String process = spec;
ArtifactVersion version = null;
ArtifactVersion upperBound = null;
ArtifactVersion lowerBound = null;
while ( process.startsWith( "[" ) || process.startsWith( "(" ) )
{
int index1 = process.indexOf( ")" );
int index2 = process.indexOf( "]" );
int index = index2;
if ( index2 < 0 || index1 < index2 )
{
if ( index1 >= 0 )
{
index = index1;
}
}
if ( index < 0 )
{
throw new InvalidVersionSpecificationException( "Unbounded range: " + spec );
}
Restriction restriction = parseRestriction( process.substring( 0, index + 1 ) );
if ( lowerBound == null )
{
lowerBound = restriction.getLowerBound();
}
if ( upperBound != null )
{
if ( restriction.getLowerBound() == null || restriction.getLowerBound().compareTo( upperBound ) < 0 )
{
throw new InvalidVersionSpecificationException( "Ranges overlap: " + spec );
}
}
restrictions.add( restriction );
upperBound = restriction.getUpperBound();
process = process.substring( index + 1 ).trim();
if ( process.length() > 0 && process.startsWith( "," ) )
{
process = process.substring( 1 ).trim();
}
}
if ( process.length() > 0 )
{
if ( restrictions.size() > 0 )
{
throw new InvalidVersionSpecificationException(
"Only fully-qualified sets allowed in multiple set scenario: " + spec );
}
else
{
version = new DefaultArtifactVersion( process );
restrictions.add( Restriction.EVERYTHING );
}
}
return new VersionRange( version, restrictions );
}
private static Restriction parseRestriction( String spec )
throws InvalidVersionSpecificationException
{
boolean lowerBoundInclusive = spec.startsWith( "[" );
boolean upperBoundInclusive = spec.endsWith( "]" );
String process = spec.substring( 1, spec.length() - 1 ).trim();
Restriction restriction;
int index = process.indexOf( "," );
if ( index < 0 )
{
if ( !lowerBoundInclusive || !upperBoundInclusive )
{
throw new InvalidVersionSpecificationException( "Single version must be surrounded by []: " + spec );
}
ArtifactVersion version = new DefaultArtifactVersion( process );
restriction = new Restriction( version, lowerBoundInclusive, version, upperBoundInclusive );
}
else
{
String lowerBound = process.substring( 0, index ).trim();
String upperBound = process.substring( index + 1 ).trim();
if ( lowerBound.equals( upperBound ) )
{
throw new InvalidVersionSpecificationException( "Range cannot have identical boundaries: " + spec );
}
ArtifactVersion lowerVersion = null;
if ( lowerBound.length() > 0 )
{
lowerVersion = new DefaultArtifactVersion( lowerBound );
}
ArtifactVersion upperVersion = null;
if ( upperBound.length() > 0 )
{
upperVersion = new DefaultArtifactVersion( upperBound );
}
if ( upperVersion != null && lowerVersion != null && upperVersion.compareTo( lowerVersion ) < 0 )
{
throw new InvalidVersionSpecificationException( "Range defies version ordering: " + spec );
}
restriction = new Restriction( lowerVersion, lowerBoundInclusive, upperVersion, upperBoundInclusive );
}
return restriction;
}
public static VersionRange createFromVersion( String version , ArtifactVersion existing) //Forge: Added existing argument
{
List<Restriction> restrictions = Collections.emptyList();
return new VersionRange(existing != null ? existing : new DefaultArtifactVersion( version ), restrictions );
}
/**
* Creates and returns a new <code>VersionRange</code> that is a restriction of this
* version range and the specified version range.
* <p>
* Note: Precedence is given to the recommended version from this version range over the
* recommended version from the specified version range.
* </p>
*
* @param restriction the <code>VersionRange</code> that will be used to restrict this version
* range.
* @return the <code>VersionRange</code> that is a restriction of this version range and the
* specified version range.
* <p>
* The restrictions of the returned version range will be an intersection of the restrictions
* of this version range and the specified version range if both version ranges have
* restrictions. Otherwise, the restrictions on the returned range will be empty.
* </p>
* <p>
* The recommended version of the returned version range will be the recommended version of
* this version range, provided that ranges falls within the intersected restrictions. If
* the restrictions are empty, this version range's recommended version is used if it is not
* <code>null</code>. If it is <code>null</code>, the specified version range's recommended
* version is used (provided it is non-<code>null</code>). If no recommended version can be
* obtained, the returned version range's recommended version is set to <code>null</code>.
* </p>
* @throws NullPointerException if the specified <code>VersionRange</code> is
* <code>null</code>.
*/
public VersionRange restrict( VersionRange restriction )
{
List<Restriction> r1 = this.restrictions;
List<Restriction> r2 = restriction.restrictions;
List<Restriction> restrictions;
if ( r1.isEmpty() || r2.isEmpty() )
{
restrictions = Collections.emptyList();
}
else
{
restrictions = intersection( r1, r2 );
}
ArtifactVersion version = null;
if ( restrictions.size() > 0 )
{
for ( Restriction r : restrictions )
{
if ( recommendedVersion != null && r.containsVersion( recommendedVersion ) )
{
// if we find the original, use that
version = recommendedVersion;
break;
}
else if ( version == null && restriction.getRecommendedVersion() != null
&& r.containsVersion( restriction.getRecommendedVersion() ) )
{
// use this if we can, but prefer the original if possible
version = restriction.getRecommendedVersion();
}
}
}
// Either the original or the specified version ranges have no restrictions
else if ( recommendedVersion != null )
{
// Use the original recommended version since it exists
version = recommendedVersion;
}
else if ( restriction.recommendedVersion != null )
{
// Use the recommended version from the specified VersionRange since there is no
// original recommended version
version = restriction.recommendedVersion;
}
/* TODO: should throw this immediately, but need artifact
else
{
throw new OverConstrainedVersionException( "Restricting incompatible version ranges" );
}
*/
return new VersionRange( version, restrictions );
}
private List<Restriction> intersection( List<Restriction> r1, List<Restriction> r2 )
{
List<Restriction> restrictions = new ArrayList<Restriction>( r1.size() + r2.size() );
Iterator<Restriction> i1 = r1.iterator();
Iterator<Restriction> i2 = r2.iterator();
Restriction res1 = i1.next();
Restriction res2 = i2.next();
boolean done = false;
while ( !done )
{
if ( res1.getLowerBound() == null || res2.getUpperBound() == null
|| res1.getLowerBound().compareTo( res2.getUpperBound() ) <= 0 )
{
if ( res1.getUpperBound() == null || res2.getLowerBound() == null
|| res1.getUpperBound().compareTo( res2.getLowerBound() ) >= 0 )
{
ArtifactVersion lower;
ArtifactVersion upper;
boolean lowerInclusive;
boolean upperInclusive;
// overlaps
if ( res1.getLowerBound() == null )
{
lower = res2.getLowerBound();
lowerInclusive = res2.isLowerBoundInclusive();
}
else if ( res2.getLowerBound() == null )
{
lower = res1.getLowerBound();
lowerInclusive = res1.isLowerBoundInclusive();
}
else
{
int comparison = res1.getLowerBound().compareTo( res2.getLowerBound() );
if ( comparison < 0 )
{
lower = res2.getLowerBound();
lowerInclusive = res2.isLowerBoundInclusive();
}
else if ( comparison == 0 )
{
lower = res1.getLowerBound();
lowerInclusive = res1.isLowerBoundInclusive() && res2.isLowerBoundInclusive();
}
else
{
lower = res1.getLowerBound();
lowerInclusive = res1.isLowerBoundInclusive();
}
}
if ( res1.getUpperBound() == null )
{
upper = res2.getUpperBound();
upperInclusive = res2.isUpperBoundInclusive();
}
else if ( res2.getUpperBound() == null )
{
upper = res1.getUpperBound();
upperInclusive = res1.isUpperBoundInclusive();
}
else
{
int comparison = res1.getUpperBound().compareTo( res2.getUpperBound() );
if ( comparison < 0 )
{
upper = res1.getUpperBound();
upperInclusive = res1.isUpperBoundInclusive();
}
else if ( comparison == 0 )
{
upper = res1.getUpperBound();
upperInclusive = res1.isUpperBoundInclusive() && res2.isUpperBoundInclusive();
}
else
{
upper = res2.getUpperBound();
upperInclusive = res2.isUpperBoundInclusive();
}
}
// don't add if they are equal and one is not inclusive
if ( lower == null || upper == null || lower.compareTo( upper ) != 0 )
{
restrictions.add( new Restriction( lower, lowerInclusive, upper, upperInclusive ) );
}
else if ( lowerInclusive && upperInclusive )
{
restrictions.add( new Restriction( lower, lowerInclusive, upper, upperInclusive ) );
}
//noinspection ObjectEquality
if ( upper == res2.getUpperBound() )
{
// advance res2
if ( i2.hasNext() )
{
res2 = i2.next();
}
else
{
done = true;
}
}
else
{
// advance res1
if ( i1.hasNext() )
{
res1 = i1.next();
}
else
{
done = true;
}
}
}
else
{
// move on to next in r1
if ( i1.hasNext() )
{
res1 = i1.next();
}
else
{
done = true;
}
}
}
else
{
// move on to next in r2
if ( i2.hasNext() )
{
res2 = i2.next();
}
else
{
done = true;
}
}
}
return restrictions;
}
//Forge: Removed getSelectedVersion and isSelectedVersion
@Override //Forge: Added @Override
public String toString()
{
if ( recommendedVersion != null )
{
return recommendedVersion.getVersionString(); //Forge: Version string specifically.
}
else
{
return Joiner.on(',').join(restrictions); //Forge: Changeed from iterator loop to joiner.
}
}
/*
//Forge: Added friendly {localized} toString
public String toStringFriendly()
{
if ( recommendedVersion != null )
{
return recommendedVersion.getVersionString();
}
else
{
List<String> friendlyRestrictions = new ArrayList<String>(restrictions.size());
for (Restriction restriction : restrictions)
{
friendlyRestrictions.add(restriction.toStringFriendly());
}
return Joiner.on(", ").join(friendlyRestrictions);
}
}
*/
public ArtifactVersion matchVersion( List<ArtifactVersion> versions )
{
// TODO: could be more efficient by sorting the list and then moving along the restrictions in order?
ArtifactVersion matched = null;
for ( ArtifactVersion version : versions )
{
if ( containsVersion( version ) )
{
// valid - check if it is greater than the currently matched version
if ( matched == null || version.compareTo( matched ) > 0 )
{
matched = version;
}
}
}
return matched;
}
public boolean containsVersion( ArtifactVersion version )
{
for ( Restriction restriction : restrictions )
{
if ( restriction.containsVersion( version ) )
{
return true;
}
}
return false;
}
public boolean hasRestrictions()
{
return !restrictions.isEmpty() && recommendedVersion == null;
}
@Override //Forge: Added @Override
public boolean equals( Object obj )
{
if ( this == obj )
{
return true;
}
if ( !( obj instanceof VersionRange ) )
{
return false;
}
VersionRange other = (VersionRange) obj;
boolean equals =
recommendedVersion == other.recommendedVersion
|| ( ( recommendedVersion != null ) && recommendedVersion.equals( other.recommendedVersion ) );
equals &=
restrictions == other.restrictions
|| ( ( restrictions != null ) && restrictions.equals( other.restrictions ) );
return equals;
}
@Override //Forge: Added @Override
public int hashCode()
{
int hash = 7;
hash = 31 * hash + ( recommendedVersion == null ? 0 : recommendedVersion.hashCode() );
hash = 31 * hash + ( restrictions == null ? 0 : restrictions.hashCode() );
return hash;
}
//Forge: Added @isUnboundedAbove
public boolean isUnboundedAbove()
{
return restrictions.size() == 1 && restrictions.get(0).getUpperBound() == null && !restrictions.get(0).isUpperBoundInclusive();
}
//Forge: Added @getLowerBoundString
public String getLowerBoundString()
{
return restrictions.size() == 1 ? restrictions.get(0).getLowerBound().getVersionString() : "";
}
//Forge: Added friendly {localized} toString
@OnlyIn(Dist.CLIENT)
public String toStringFriendly()
{
if ( recommendedVersion != null )
{
return recommendedVersion.getVersionString();
}
else
{
List<String> friendlyRestrictions = new ArrayList<String>(restrictions.size());
for (Restriction restriction : restrictions)
{
friendlyRestrictions.add(restriction.toStringFriendly());
}
return Joiner.on(", ").join(friendlyRestrictions);
}
}
}

View file

@ -20,7 +20,7 @@
package net.minecraftforge.fml.language; package net.minecraftforge.fml.language;
import com.electronwill.nightconfig.core.UnmodifiableConfig; import com.electronwill.nightconfig.core.UnmodifiableConfig;
import net.minecraftforge.fml.common.versioning.VersionRange; import org.apache.maven.artifact.versioning.VersionRange;
import java.net.URL; import java.net.URL;
import java.util.List; import java.util.List;

View file

@ -20,15 +20,16 @@
package net.minecraftforge.fml.language; package net.minecraftforge.fml.language;
import com.electronwill.nightconfig.core.UnmodifiableConfig; import com.electronwill.nightconfig.core.UnmodifiableConfig;
import net.minecraftforge.fml.common.versioning.ArtifactVersion; import net.minecraftforge.fml.loading.MavenVersionAdapter;
import net.minecraftforge.fml.common.versioning.VersionRange;
import net.minecraftforge.fml.loading.FMLEnvironment; import net.minecraftforge.fml.loading.FMLEnvironment;
import org.apache.maven.artifact.versioning.ArtifactVersion;
import org.apache.maven.artifact.versioning.VersionRange;
import java.util.List; import java.util.List;
public interface IModInfo public interface IModInfo
{ {
VersionRange UNBOUNDED = VersionRange.createFromVersionSpec(""); VersionRange UNBOUNDED = MavenVersionAdapter.createFromVersionSpec("");
IModFileInfo getOwningFile(); IModFileInfo getOwningFile();
@ -69,7 +70,7 @@ public interface IModInfo
this.owner = owner; this.owner = owner;
this.modId = config.get("modId"); this.modId = config.get("modId");
this.versionRange = config.getOptional("versionRange").map(String.class::cast). this.versionRange = config.getOptional("versionRange").map(String.class::cast).
map(VersionRange::createFromVersionSpec).orElse(UNBOUNDED); map(MavenVersionAdapter::createFromVersionSpec).orElse(UNBOUNDED);
this.mandatory = config.get("mandatory"); this.mandatory = config.get("mandatory");
this.ordering = config.getOptional("ordering").map(String.class::cast). this.ordering = config.getOptional("ordering").map(String.class::cast).
map(Ordering::valueOf).orElse(Ordering.NONE); map(Ordering::valueOf).orElse(Ordering.NONE);

View file

@ -20,13 +20,13 @@
package net.minecraftforge.fml.loading; package net.minecraftforge.fml.loading;
import net.minecraftforge.common.ForgeVersion; import net.minecraftforge.common.ForgeVersion;
import net.minecraftforge.fml.common.versioning.ArtifactVersion;
import net.minecraftforge.fml.common.versioning.DefaultArtifactVersion;
import net.minecraftforge.fml.common.versioning.VersionRange;
import net.minecraftforge.fml.language.IModLanguageProvider; import net.minecraftforge.fml.language.IModLanguageProvider;
import net.minecraftforge.fml.loading.moddiscovery.ModFile; import net.minecraftforge.fml.loading.moddiscovery.ModFile;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.apache.maven.artifact.versioning.ArtifactVersion;
import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
import org.apache.maven.artifact.versioning.VersionRange;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.ArrayList; import java.util.ArrayList;

View file

@ -0,0 +1,90 @@
package net.minecraftforge.fml.loading;
import net.minecraftforge.fml.ForgeI18n;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.maven.artifact.versioning.ArtifactVersion;
import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
import org.apache.maven.artifact.versioning.Restriction;
import org.apache.maven.artifact.versioning.VersionRange;
import java.util.Objects;
import java.util.stream.Collectors;
import static net.minecraftforge.fml.Logging.CORE;
public final class MavenVersionAdapter {
private static final Logger LOGGER = LogManager.getLogger();
private MavenVersionAdapter() {}
public static VersionRange createFromVersionSpec(final String spec) {
try {
return VersionRange.createFromVersionSpec(spec);
} catch (InvalidVersionSpecificationException e) {
LOGGER.error(CORE, "Failed to parse version spec {}", spec, e);
throw new RuntimeException("Failed to parse spec", e);
}
}
public static String artifactVersionToString(final ArtifactVersion artifactVersion) {
return artifactVersion.toString();
}
public static String versionRangeToString(final VersionRange range) {
return range.getRestrictions().stream().map(MavenVersionAdapter::restrictionToString).collect(Collectors.joining(","));
}
public static String restrictionToString(final Restriction restriction) {
if ( restriction.getLowerBound() == null && restriction.getUpperBound() == null )
{
return ForgeI18n.parseMessage("fml.messages.version.restriction.any");
}
else if ( restriction.getLowerBound() != null && restriction.getUpperBound() != null )
{
if (Objects.equals(artifactVersionToString(restriction.getLowerBound()), artifactVersionToString(restriction.getUpperBound())))
{
return artifactVersionToString(restriction.getLowerBound());
}
else
{
if (restriction.isLowerBoundInclusive() && restriction.isUpperBoundInclusive())
{
return ForgeI18n.parseMessage("fml.messages.version.restriction.bounded.inclusive", restriction.getLowerBound(), restriction.getUpperBound());
}
else if (restriction.isLowerBoundInclusive())
{
return ForgeI18n.parseMessage("fml.messages.version.restriction.bounded.upperexclusive", restriction.getLowerBound(), restriction.getUpperBound());
}
else if (restriction.isUpperBoundInclusive())
{
return ForgeI18n.parseMessage("fml.messages.version.restriction.bounded.lowerexclusive", restriction.getLowerBound(), restriction.getUpperBound());
}
else
{
return ForgeI18n.parseMessage("fml.messages.version.restriction.bounded.exclusive", restriction.getLowerBound(), restriction.getUpperBound());
}
}
}
else if ( restriction.getLowerBound() != null )
{
if ( restriction.isLowerBoundInclusive() )
{
return ForgeI18n.parseMessage("fml.messages.version.restriction.lower.inclusive", restriction.getLowerBound());
}
else
{
return ForgeI18n.parseMessage("fml.messages.version.restriction.lower.exclusive", restriction.getLowerBound());
}
}
else
{
if ( restriction.isUpperBoundInclusive() )
{
return ForgeI18n.parseMessage("fml.messages.version.restriction.upper.inclusive", restriction.getUpperBound());
}
else
{
return ForgeI18n.parseMessage("fml.messages.version.restriction.upper.exclusive", restriction.getUpperBound());
}
}
}
}

View file

@ -21,13 +21,13 @@ package net.minecraftforge.fml.loading;
import net.minecraftforge.fml.Java9BackportUtils; import net.minecraftforge.fml.Java9BackportUtils;
import net.minecraftforge.fml.common.toposort.TopologicalSort; import net.minecraftforge.fml.common.toposort.TopologicalSort;
import net.minecraftforge.fml.common.versioning.ArtifactVersion;
import net.minecraftforge.fml.language.IModInfo; import net.minecraftforge.fml.language.IModInfo;
import net.minecraftforge.fml.loading.moddiscovery.ModFile; import net.minecraftforge.fml.loading.moddiscovery.ModFile;
import net.minecraftforge.fml.loading.moddiscovery.ModFileInfo; import net.minecraftforge.fml.loading.moddiscovery.ModFileInfo;
import net.minecraftforge.fml.loading.moddiscovery.ModInfo; import net.minecraftforge.fml.loading.moddiscovery.ModInfo;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.apache.maven.artifact.versioning.ArtifactVersion;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;

View file

@ -20,10 +20,11 @@
package net.minecraftforge.fml.loading.moddiscovery; package net.minecraftforge.fml.loading.moddiscovery;
import com.electronwill.nightconfig.core.UnmodifiableConfig; import com.electronwill.nightconfig.core.UnmodifiableConfig;
import net.minecraftforge.fml.common.versioning.VersionRange; import net.minecraftforge.fml.loading.MavenVersionAdapter;
import net.minecraftforge.fml.language.IModFileInfo; import net.minecraftforge.fml.language.IModFileInfo;
import net.minecraftforge.fml.language.IModInfo; import net.minecraftforge.fml.language.IModInfo;
import net.minecraftforge.fml.loading.StringUtils; import net.minecraftforge.fml.loading.StringUtils;
import org.apache.maven.artifact.versioning.VersionRange;
import java.net.URL; import java.net.URL;
import java.util.ArrayList; import java.util.ArrayList;
@ -50,7 +51,7 @@ public class ModFileInfo implements IModFileInfo
this.modLoader = config.<String>getOptional("modLoader"). this.modLoader = config.<String>getOptional("modLoader").
orElseThrow(()->new InvalidModFileException("Missing ModLoader in file", this)); orElseThrow(()->new InvalidModFileException("Missing ModLoader in file", this));
this.modLoaderVersion = config.<String>getOptional("loaderVersion"). this.modLoaderVersion = config.<String>getOptional("loaderVersion").
map(VersionRange::createFromVersionSpec). map(MavenVersionAdapter::createFromVersionSpec).
orElseThrow(()->new InvalidModFileException("Missing ModLoader version in file", this)); orElseThrow(()->new InvalidModFileException("Missing ModLoader version in file", this));
this.properties = config.<UnmodifiableConfig>getOptional("properties"). this.properties = config.<UnmodifiableConfig>getOptional("properties").
map(UnmodifiableConfig::valueMap).orElse(Collections.emptyMap()); map(UnmodifiableConfig::valueMap).orElse(Collections.emptyMap());

View file

@ -22,8 +22,6 @@ package net.minecraftforge.fml.loading.moddiscovery;
import com.electronwill.nightconfig.core.UnmodifiableConfig; import com.electronwill.nightconfig.core.UnmodifiableConfig;
import net.minecraftforge.fml.language.IModInfo; import net.minecraftforge.fml.language.IModInfo;
import net.minecraftforge.fml.loading.StringSubstitutor; import net.minecraftforge.fml.loading.StringSubstitutor;
import net.minecraftforge.fml.common.versioning.ArtifactVersion;
import net.minecraftforge.fml.common.versioning.DefaultArtifactVersion;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
@ -32,7 +30,8 @@ import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import net.minecraftforge.fml.language.IModInfo.ModVersion; import org.apache.maven.artifact.versioning.ArtifactVersion;
import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
public class ModInfo implements IModInfo public class ModInfo implements IModInfo
{ {

View file

@ -24,6 +24,17 @@
"fml.modloading.errorduringevent":"{0,modinfo,name} ({0,modinfo,id}) encountered an error during the {1,lower} event phase\n\u00a77{2,exc,msg}", "fml.modloading.errorduringevent":"{0,modinfo,name} ({0,modinfo,id}) encountered an error during the {1,lower} event phase\n\u00a77{2,exc,msg}",
"fml.modloading.failedtoloadforge": "Failed to load forge", "fml.modloading.failedtoloadforge": "Failed to load forge",
"fml.messages.version.restriction.any":"any",
"fml.messages.version.restriction.lower.inclusive":"{0} or above",
"fml.messages.version.restriction.lower.exclusive":"above {0}",
"fml.messages.version.restriction.upper.inclusive":"{0} or below",
"fml.messages.version.restriction.upper.exclusive":"below {0}",
"fml.messages.version.restriction.bounded":"between {0} and {1}",
"fml.messages.version.restriction.bounded.inclusive":"between {0} and {1} (inclusive)",
"fml.messages.version.restriction.bounded.exclusive":"between {0} and {1} (exclusive)",
"fml.messages.version.restriction.bounded.lowerexclusive":"above {0}, and {1} or below",
"fml.messages.version.restriction.bounded.upperexclusive":"{0} or above, and below {1}",
"commands.forge.dimensions.list": "Currently registered dimensions by type:", "commands.forge.dimensions.list": "Currently registered dimensions by type:",
"commands.forge.entity.list.invalid": "Invalid filter, does not match any entities. Use /forge entity list for a proper list", "commands.forge.entity.list.invalid": "Invalid filter, does not match any entities. Use /forge entity list for a proper list",
"commands.forge.entity.list.invalidworld": "Could not load world for dimension {0}. Please select a valid dimension.", "commands.forge.entity.list.invalidworld": "Could not load world for dimension {0}. Please select a valid dimension.",

View file

@ -1,323 +0,0 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2018.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.minecraftforge.fml.test;
import static org.junit.jupiter.api.Assertions.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import com.google.common.collect.ImmutableList;
import net.minecraftforge.fml.common.versioning.DependencyParser;
import net.minecraftforge.api.distmarker.Dist;
import com.google.common.base.Functions;
import com.google.common.collect.Collections2;
import com.google.common.collect.Sets;
import net.minecraftforge.fml.common.LoaderException;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
public class DependencyParserTest
{
private static DependencyParser clientDependencyParser;
private static DependencyParser serverDependencyParser;
private static List<DependencyParser> parsers;
@BeforeAll
public static void beforeAll()
{
clientDependencyParser = new DependencyParser("test", Side.CLIENT);
serverDependencyParser = new DependencyParser("test", Side.SERVER);
parsers = ImmutableList.of(clientDependencyParser, serverDependencyParser);
}
@Test
public void testParsingNothing()
{
List<String> strings = new ArrayList<>();
strings.add(null);
strings.add("");
strings.add(";;;;;;;");
strings.add("; ; ; ; ; ; ; ");
for (String string : strings)
{
for (DependencyParser parser : parsers)
{
DependencyParser.DependencyInfo info = parser.parseDependencies(string);
assertTrue(info.requirements.isEmpty());
assertTrue(info.dependants.isEmpty());
assertTrue(info.dependencies.isEmpty());
}
}
}
@Test
public void testParsingRequired()
{
String mod = "supermod3000@[1.2,)";
for (DependencyParser parser : parsers)
{
DependencyParser.DependencyInfo info = parser.parseDependencies("required:" + mod);
assertContainsSameToString(info.requirements, Sets.newHashSet(mod));
assertTrue(info.dependants.isEmpty());
assertTrue(info.dependencies.isEmpty());
}
}
@Test
public void testParsingBefore()
{
String mod = "supermod3000@[1.2,)";
for (DependencyParser parser : parsers)
{
DependencyParser.DependencyInfo info = parser.parseDependencies("before:" + mod);
assertTrue(info.requirements.isEmpty());
assertContainsSameToString(info.dependants, Sets.newHashSet(mod));
assertTrue(info.dependencies.isEmpty());
}
}
@Test
public void testParsingAfter()
{
String mod = "supermod3000@[1.2,)";
for (DependencyParser parser : parsers)
{
DependencyParser.DependencyInfo info = parser.parseDependencies("after:" + mod);
assertTrue(info.requirements.isEmpty());
assertTrue(info.dependants.isEmpty());
assertContainsSameToString(info.dependencies, Sets.newHashSet(mod));
}
}
@Test
public void testParsingNoPrefix()
{
String mod = "supermod3000@[1.2,)";
for (DependencyParser parser : parsers)
{
assertThrows(LoaderException.class, () -> {
parser.parseDependencies(mod);
});
}
}
@Test
public void testParsingCombined()
{
for (DependencyParser parser : parsers)
{
String dependencyString = "after:supermod2000@[1.3,);required-before:yetanothermod;required:modw";
DependencyParser.DependencyInfo info = parser.parseDependencies(dependencyString);
assertContainsSameToString(info.requirements, Sets.newHashSet("yetanothermod", "modw"));
assertContainsSameToString(info.dependencies, Sets.newHashSet("supermod2000@[1.3,)"));
assertContainsSameToString(info.dependants, Sets.newHashSet("yetanothermod"));
}
}
@Test
public void testParsingSided()
{
String mod = "testmod@[1.0,2.0)";
{
DependencyParser.DependencyInfo info = clientDependencyParser.parseDependencies("client-after:" + mod);
assertTrue(info.requirements.isEmpty());
assertTrue(info.dependants.isEmpty());
assertContainsSameToString(info.dependencies, Sets.newHashSet(mod));
}
{
DependencyParser.DependencyInfo info = clientDependencyParser.parseDependencies("server-after:testmod@[1.0,2.0);server-required:testmod2;server-after:testmod3;server-before:testmod4");
assertTrue(info.requirements.isEmpty());
assertTrue(info.dependants.isEmpty());
assertTrue(info.dependencies.isEmpty());
}
{
DependencyParser.DependencyInfo info = clientDependencyParser.parseDependencies("client-before:testmod@[1.0,2.0);server-required:testmod2;server-after:testmod3;server-before:testmod4");
assertTrue(info.requirements.isEmpty());
assertContainsSameToString(info.dependants, Sets.newHashSet(mod));
assertTrue(info.dependencies.isEmpty());
}
{
DependencyParser.DependencyInfo info = serverDependencyParser.parseDependencies("server-before:" + mod);
assertTrue(info.requirements.isEmpty());
assertContainsSameToString(info.dependants, Sets.newHashSet(mod));
assertTrue(info.dependencies.isEmpty());
}
{
DependencyParser.DependencyInfo info = serverDependencyParser.parseDependencies("client-before:testmod@[1.0,2.0);client-required:testmod2;client-after:testmod3;client-before:testmod4");
assertTrue(info.requirements.isEmpty());
assertTrue(info.dependants.isEmpty());
assertTrue(info.dependencies.isEmpty());
}
{
DependencyParser.DependencyInfo info = serverDependencyParser.parseDependencies("server-before:testmod@[1.0,2.0);client-required:testmod2;client-after:testmod3;client-before:testmod4");
assertTrue(info.requirements.isEmpty());
assertContainsSameToString(info.dependants, Sets.newHashSet(mod));
assertTrue(info.dependencies.isEmpty());
}
}
@Test
public void testParsingInvalidDependencyInstructions()
{
for (DependencyParser parser : parsers)
{
assertThrows(LoaderException.class, () -> {
parser.parseDependencies("gibberishtext:amod");
});
}
}
@Test
public void testParsingInvalidDependencyVersionClient()
{
for (DependencyParser parser : parsers)
{
assertThrows(LoaderException.class, () -> {
parser.parseDependencies("amod@[10");
});
assertThrows(LoaderException.class, () -> {
parser.parseDependencies("client:amod@[10");
});
assertThrows(LoaderException.class, () -> {
parser.parseDependencies("server:amod@[10");
});
}
}
// TODO: enable this in 1.13
// @Test(expected = LoaderException.class)
// public void testParsingUppercaseModId()
// {
// for (DependencyParser parser : parsers)
// {
// assertThrows(LoaderException.class, () -> {
// parser.parseDependencies("Forge@[1.0]");
// });
// assertThrows(LoaderException.class, () -> {
// parser.parseDependencies("client:Forge@[1.0]");
// });
// assertThrows(LoaderException.class, () -> {
// parser.parseDependencies("server:Forge@[1.0]");
// });
// }
// }
@Test
public void testParsingSoftDepWithNoVersion()
{
for (DependencyParser parser : parsers)
{
assertThrows(LoaderException.class, () -> {
parser.parseDependencies("amod");
});
assertThrows(LoaderException.class, () -> {
parser.parseDependencies("client:amod");
});
assertThrows(LoaderException.class, () -> {
parser.parseDependencies("server:amod");
});
}
}
@Test
public void testParsingDepAfterAll()
{
for (DependencyParser parser : parsers)
{
parser.parseDependencies("after:*");
}
}
@Test
public void testParsingDepBeforeAll()
{
for (DependencyParser parser : parsers)
{
parser.parseDependencies("before:*");
}
}
@Test
public void testParsingDepOnAll()
{
for (DependencyParser parser : parsers)
{
assertThrows(LoaderException.class, () -> {
parser.parseDependencies("*");
});
}
}
@Test
public void testParsingSidedDepOnAll()
{
for (DependencyParser parser : parsers)
{
assertThrows(LoaderException.class, () -> {
parser.parseDependencies("client:*");
});
}
}
@Test
public void testParsingRequireAll()
{
for (DependencyParser parser : parsers)
{
assertThrows(LoaderException.class, () -> {
parser.parseDependencies("required:*");
});
}
}
@Test
public void testParsingVersionedAll()
{
for (DependencyParser parser : parsers)
{
assertThrows(LoaderException.class, () -> {
parser.parseDependencies("*@[1.0]");
});
}
}
public static void assertContainsSameToString(Collection<?> c1, Collection<String> expected)
{
Collection<String> transformedToString = Collections2.transform(c1, Functions.toStringFunction());
assertContainsSame(transformedToString, expected);
}
public static <T> void assertContainsSame(Collection<T> c1, Collection<T> c2)
{
if (!c1.containsAll(c2) || !c2.containsAll(c1))
{
fail(c1 + " does not contain the same as " + c2);
}
}
}