Skip to content

Commit

Permalink
Added in implementation of naming service. I'm going to call this
Browse files Browse the repository at this point in the history
version 1 of modlauncher.

Signed-off-by: cpw <cpw+github@weeksfamily.ca>
  • Loading branch information
cpw committed Apr 6, 2019
1 parent f4037fb commit 745b6f9
Show file tree
Hide file tree
Showing 11 changed files with 120 additions and 26 deletions.
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ tasks['jmh'].dependsOn(clean)
ext.sharedManifest = manifest {
attributes(["Specification-Title": "modlauncher",
"Specification-Vendor": "Forge",
"Specification-Version": "1.0", // We are version 1 of the modlauncher specification
"Specification-Version": "2.0", // We are version 1 of the modlauncher specification

This comment has been minimized.

Copy link
@mezz

mezz Apr 6, 2019

accident or intended?

"Implementation-Title": project.name,
"Implementation-Version": "${version}+${System.getenv("BUILD_NUMBER")?:0}+${grgit.head().abbreviatedId}",
"Implementation-Vendor" :"Forge",
Expand Down
7 changes: 6 additions & 1 deletion src/main/java/cpw/mods/modlauncher/Environment.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
import cpw.mods.modlauncher.serviceapi.*;

import java.util.*;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Supplier;

/**
* Environment implementation class
Expand Down Expand Up @@ -34,6 +34,11 @@ public Optional<ILaunchHandlerService> findLaunchHandler(final String name) {
return launcher.findLaunchHandler(name);
}

@Override
public Optional<BiFunction<INameMappingService.Domain, String, String>> findNameMapping(final String targetMapping) {
return launcher.findNameMapping(targetMapping);
}

@Override
public <T> T computePropertyIfAbsent(final TypesafeMap.Key<T> key, final Function<? super TypesafeMap.Key<T>, ? extends T> valueFunction) {
return environment.computeIfAbsent(key, valueFunction);
Expand Down
11 changes: 8 additions & 3 deletions src/main/java/cpw/mods/modlauncher/Launcher.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import org.apache.logging.log4j.LogManager;

import java.util.*;
import java.util.function.BiFunction;

import static cpw.mods.modlauncher.LogMarkers.*;

Expand Down Expand Up @@ -48,7 +49,7 @@ public final TypesafeMap blackboard() {

private void run(String... args) {
this.argumentHandler.setArgs(args);
this.transformationServicesHandler.initializeTransformationServices(this.argumentHandler, this.environment);
this.transformationServicesHandler.initializeTransformationServices(this.argumentHandler, this.environment, this.nameMappingServiceHandler);
this.launchService.validateLaunchTarget(this.argumentHandler);
final TransformingClassLoaderBuilder classLoaderBuilder = this.launchService.identifyTransformationTargets(this.argumentHandler);
this.classLoader = this.transformationServicesHandler.buildTransformingClassLoader(this.launchPlugins, classLoaderBuilder);
Expand All @@ -60,11 +61,15 @@ public Environment environment() {
return this.environment;
}

public Optional<ILaunchPluginService> findLaunchPlugin(final String name) {
Optional<ILaunchPluginService> findLaunchPlugin(final String name) {
return launchPlugins.get(name);
}

public Optional<ILaunchHandlerService> findLaunchHandler(final String name) {
Optional<ILaunchHandlerService> findLaunchHandler(final String name) {
return launchService.findLaunchHandler(name);
}

Optional<BiFunction<INameMappingService.Domain, String, String>> findNameMapping(final String targetMapping) {
return nameMappingServiceHandler.findNameTranslator(targetMapping);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

import cpw.mods.modlauncher.api.*;

import java.util.Objects;
import java.util.function.BiFunction;

/**
* Decorator for Naming Services
*/
Expand All @@ -11,4 +14,19 @@ class NameMappingServiceDecorator {
public NameMappingServiceDecorator(INameMappingService service) {
this.service = service;
}

public boolean validTarget(final String origin) {
return Objects.equals(this.service.understanding().getValue(), origin);
}
public String understands() {
return this.service.understanding().getKey();
}

public BiFunction<INameMappingService.Domain, String, String> function() {
return this.service.namingFunction();
}

public String toString() {
return this.service.mappingName() + ":" + this.service.mappingVersion();
}
}
24 changes: 20 additions & 4 deletions src/main/java/cpw/mods/modlauncher/NameMappingServiceHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
import org.apache.logging.log4j.Logger;

import java.util.*;
import java.util.stream.*;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.stream.Collectors;

import static cpw.mods.modlauncher.LogMarkers.*;

Expand All @@ -15,11 +17,25 @@
class NameMappingServiceHandler {
private static final Logger LOGGER = LogManager.getLogger();
private final ServiceLoader<INameMappingService> namingServices;
private final Map<String, NameMappingServiceDecorator> namingLookup;
private final Map<String, NameMappingServiceDecorator> namingTable;
private Map<String, NameMappingServiceDecorator> nameBindings;

public NameMappingServiceHandler() {
namingServices = ServiceLoaderStreamUtils.errorHandlingServiceLoader(INameMappingService.class, serviceConfigurationError -> LOGGER.fatal("Encountered serious error loading naming service, expect problems", serviceConfigurationError));
namingLookup = ServiceLoaderStreamUtils.toMap(namingServices, INameMappingService::mappingName, NameMappingServiceDecorator::new);
LOGGER.debug(MODLAUNCHER,"Found naming services {}", () -> String.join(",", namingLookup.keySet()));
namingTable = ServiceLoaderStreamUtils.toMap(namingServices, INameMappingService::mappingName, NameMappingServiceDecorator::new);
LOGGER.debug(MODLAUNCHER,"Found naming services : [{}]", () -> String.join(",", namingTable.keySet()));
}


public Optional<BiFunction<INameMappingService.Domain,String,String>> findNameTranslator(final String targetNaming) {
return Optional.ofNullable(nameBindings.get(targetNaming)).map(NameMappingServiceDecorator::function);
}

public void bindNamingServices(final String currentNaming) {
LOGGER.debug(MODLAUNCHER, "Current naming domain is '{}'", currentNaming);
nameBindings = namingTable.values().stream().
filter(nameMappingServiceDecorator -> nameMappingServiceDecorator.validTarget(currentNaming)).
collect(Collectors.toMap(NameMappingServiceDecorator::understands, Function.identity()));
LOGGER.debug(MODLAUNCHER, "Identified name mapping providers {}", nameBindings);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -80,4 +80,10 @@ public void gatherTransformers(TransformStore transformStore) {
ITransformationService getService() {
return service;
}

void runScan(final Environment environment) {
LOGGER.debug(MODLAUNCHER,"Beginning scan trigger - transformation service {}", this.service::name);
this.service.beginScanning(environment);
LOGGER.debug(MODLAUNCHER,"End scan trigger - transformation service {}", this.service::name);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,15 @@ class TransformationServicesHandler {
this.transformStore = transformStore;
}

void initializeTransformationServices(ArgumentHandler argumentHandler, Environment environment) {
void initializeTransformationServices(ArgumentHandler argumentHandler, Environment environment, final NameMappingServiceHandler nameMappingServiceHandler) {
loadTransformationServices(environment);
validateTransformationServices();
processArguments(argumentHandler, environment);
initialiseTransformationServices(environment);
// force the naming to "mojang" if nothing has been populated during transformer setup
environment.computePropertyIfAbsent(IEnvironment.Keys.NAMING.get(), a-> "mojang");
nameMappingServiceHandler.bindNamingServices(environment.getProperty(Environment.Keys.NAMING.get()).orElse("mojang"));
runScanningTransformationServices(environment);
initialiseServiceTransformers();
}

Expand Down Expand Up @@ -68,6 +72,12 @@ private void initialiseTransformationServices(Environment environment) {
serviceLookup.values().forEach(s -> s.onInitialize(environment));
}

private void runScanningTransformationServices(Environment environment) {
LOGGER.debug(MODLAUNCHER,"Transformation services begin scanning");

serviceLookup.values().forEach(s -> s.runScan(environment));
}

private void validateTransformationServices() {
if (serviceLookup.values().stream().filter(d -> !d.isValid()).count() > 0) {
final List<ITransformationService> services = serviceLookup.values().stream().filter(d -> !d.isValid()).map(TransformationServiceDecorator::getService).collect(Collectors.toList());
Expand Down
23 changes: 23 additions & 0 deletions src/main/java/cpw/mods/modlauncher/api/IEnvironment.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,34 @@ public interface IEnvironment {
*/
Optional<ILaunchHandlerService> findLaunchHandler(String name);

/**
* Find the naming translation for the targetMapping.
* @param targetMapping the name of the mapping to lookup
* @return a function mapping names from the current naming domain to the requested one, if available
*/
Optional<BiFunction<INameMappingService.Domain, String, String>> findNameMapping(String targetMapping);

final class Keys {
/**
* Version passed in through arguments
*/
public static final Supplier<TypesafeMap.Key<String>> VERSION = buildKey("version", String.class);
/**
* The identified game directory (usually passed as an argument)
*/
public static final Supplier<TypesafeMap.Key<Path>> GAMEDIR = buildKey("gamedir", Path.class);
/**
* The identified assets directory (usually passed as an argument)
*/
public static final Supplier<TypesafeMap.Key<Path>> ASSETSDIR = buildKey("assetsdir", Path.class);
/**
* The name of the identified launch target (passed as an argument)
*/
public static final Supplier<TypesafeMap.Key<String>> LAUNCHTARGET = buildKey("launchtarget", String.class);
/**
* The naming scheme in use. Populated at startup. See: {@link INameMappingService}
*/
public static final Supplier<TypesafeMap.Key<String>> NAMING = buildKey("naming", String.class);
}


Expand Down
27 changes: 13 additions & 14 deletions src/main/java/cpw/mods/modlauncher/api/INameMappingService.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,16 @@
import java.util.function.*;

/**
* Expose known naming domains into the system, to allow for modules to
* lookup alternative namings.
* notch namemappings will always be available. srg and mcp will be available in certain environments.
* Expose known naming domains into the system, to allow for modules to lookup alternative namings.
*
* mojang, srg and mcp will be available in certain environments.
*/
public interface INameMappingService {
/**
* The name of this namemapping.
*
* E.G. srgtomcp
*
* @return a unique name for this mapping
*/
String mappingName();
Expand All @@ -24,23 +26,20 @@ public interface INameMappingService {
String mappingVersion();

/**
* The set of mapping targets this namemapping understands.
* Trivially, you should understand yourself.
* The source and target you support. If your target is not the active naming, you will be ignored.
*
* @return A set of other mapping targets you can translate to.
* @return A key (source naming) value (target naming) pair representing your source to target translation.
*/
Set<String> understanding();
Map.Entry<String,String> understanding();

/**
* A function mapping a name to another name, for the given domain
* and naming target.
* A function mapping a name to another name, for the given domain.
*
* The input string will be the name in the source naming, you should return the name in the target naming.
*
* @param domain The naming domain
* @param target The target from {@link #understanding} for which
* we wish to map the names
* @return A function mapping names
*/
Function<String, String> namingFunction(Domain domain, String target);
BiFunction<Domain, String, String> namingFunction();

enum Domain {CLASS, METHOD, FIELD}
enum Domain { CLASS, METHOD, FIELD }
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,20 @@ default void argumentValues(OptionResult option) {
}

/**
* Initialize your service. Scan for mods (but don't classload them), identify metadata that might drive
* game functionality.
* Initialize your service.
*
* @param environment environment - query state from here to determine viability
*/
void initialize(IEnvironment environment);


/**
* Scan for mods (but don't classload them), identify metadata that might drive
* game functionality.
*
* @param environment environment
*/
void beginScanning(IEnvironment environment);
/**
* Load your service. Called immediately on loading with a list of other services found.
* Use to identify and immediately indicate incompatibilities with other services, and environment
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ public void initialize(IEnvironment environment) {
state = "INITIALIZED";
}

@Override
public void beginScanning(final IEnvironment environment) {
// noop
}

@Override
public void onLoad(IEnvironment env, Set<String> otherServices) throws IncompatibleEnvironmentException {

Expand Down

2 comments on commit 745b6f9

@cpw
Copy link
Member Author

@cpw cpw commented on 745b6f9 Apr 8, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mezz intended. The new modlauncher is binary incompatible. It needs a new version number.

@Alpvax
Copy link

@Alpvax Alpvax commented on 745b6f9 Apr 9, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should probably update the comment then.

Please sign in to comment.