Merge remote-tracking branch 'origin/nui-gestalt-separation' into feature/migrate-gestalt-v7
engine/src/main/java/org/terasology/engine/config/flexible/ui/AutoConfigWidgetFactory.java engine/src/main/java/org/terasology/engine/config/flexible/ui/SettingWidgetFactory.java engine/src/main/java/org/terasology/engine/logic/players/LocalPlayerSystem.java engine/src/main/java/org/terasology/engine/network/internal/ClientConnectionHandler.java engine/src/main/java/org/terasology/engine/rendering/nui/layers/mainMenu/EnterUsernamePopup.java engine/src/main/java/org/terasology/engine/rendering/nui/layers/mainMenu/JoinGameScreen.java engine/src/main/java/org/terasology/engine/rendering/nui/layers/mainMenu/SelectionScreen.java engine/src/main/java/org/terasology/engine/rendering/nui/layers/mainMenu/settings/PlayerSettingsScreen.javadevelop
commit
2f9d4afce7
|
@ -26,8 +26,8 @@ class SettingWidgetFactoryTest {
|
|||
.thenReturn(Lists.newArrayList(NumberRangeConstraintWidgetFactory.class));
|
||||
|
||||
AssetManager assetManager = new AssetManager(mock(AssetTypeManager.class));
|
||||
|
||||
SettingWidgetFactory settingWidgetFactory = new SettingWidgetFactory(environment, assetManager);
|
||||
SettingWidgetFactory settingWidgetFactory = new SettingWidgetFactory(environment, assetManager,
|
||||
null);
|
||||
|
||||
Setting<Integer> setting = mock(Setting.class);
|
||||
|
||||
|
|
|
@ -1,18 +1,5 @@
|
|||
/*
|
||||
* Copyright 2013 MovingBlocks
|
||||
*
|
||||
* Licensed 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.
|
||||
*/
|
||||
// Copyright 2021 The Terasology Foundation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package org.terasology.engine.config;
|
||||
|
||||
|
@ -93,10 +80,6 @@ public final class Config {
|
|||
return config.getNetwork();
|
||||
}
|
||||
|
||||
public PlayerConfig getPlayer() {
|
||||
return config.getPlayer();
|
||||
}
|
||||
|
||||
public RenderingConfig getRendering() {
|
||||
return config.getRendering();
|
||||
}
|
||||
|
|
|
@ -1,108 +1,62 @@
|
|||
/*
|
||||
* Copyright 2017 MovingBlocks
|
||||
*
|
||||
* Licensed 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.
|
||||
*/
|
||||
// Copyright 2021 The Terasology Foundation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package org.terasology.engine.config;
|
||||
|
||||
import org.terasology.nui.Color;
|
||||
import org.terasology.engine.config.flexible.AutoConfig;
|
||||
import org.terasology.engine.config.flexible.Setting;
|
||||
import org.terasology.engine.config.flexible.constraints.ColorConstraint;
|
||||
import org.terasology.engine.config.flexible.constraints.NumberRangeConstraint;
|
||||
import org.terasology.engine.config.flexible.constraints.StringConstraint;
|
||||
import org.terasology.engine.rendering.nui.layers.mainMenu.settings.CieCamColors;
|
||||
import org.terasology.engine.utilities.random.FastRandom;
|
||||
import org.terasology.engine.utilities.random.Random;
|
||||
import org.terasology.engine.utilities.subscribables.AbstractSubscribable;
|
||||
import org.terasology.nui.Color;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class PlayerConfig extends AbstractSubscribable {
|
||||
import static org.terasology.engine.config.flexible.SettingArgument.constraint;
|
||||
import static org.terasology.engine.config.flexible.SettingArgument.defaultValue;
|
||||
import static org.terasology.engine.config.flexible.SettingArgument.name;
|
||||
import static org.terasology.engine.config.flexible.SettingArgument.type;
|
||||
|
||||
public static final String DISCORD_PRESENCE = "DISCORD_PRESENCE";
|
||||
public static final String PLAYER_NAME = "PLAYER_NAME";
|
||||
public class PlayerConfig extends AutoConfig {
|
||||
|
||||
private static final float DEFAULT_PLAYER_HEIGHT = 1.8f;
|
||||
|
||||
private static final float DEFAULT_PLAYER_EYE_HEIGHT = 0.85f;
|
||||
|
||||
private static final boolean DEFAULT_DISCORD_PRESENCE = true;
|
||||
|
||||
private String name = defaultPlayerName();
|
||||
|
||||
private Color color = defaultPlayerColor();
|
||||
|
||||
private Float height = DEFAULT_PLAYER_HEIGHT;
|
||||
|
||||
private Float eyeHeight = DEFAULT_PLAYER_EYE_HEIGHT;
|
||||
|
||||
private boolean hasEnteredUsername;
|
||||
|
||||
private boolean discordPresence = DEFAULT_DISCORD_PRESENCE;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
String oldName = this.name;
|
||||
this.name = name;
|
||||
propertyChangeSupport.firePropertyChange(PLAYER_NAME, oldName, name);
|
||||
}
|
||||
|
||||
public Color getColor() {
|
||||
return color;
|
||||
}
|
||||
|
||||
public void setColor(Color color) {
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
public Float getHeight() {
|
||||
return height;
|
||||
}
|
||||
|
||||
public void setHeight(Float height) {
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
public Float getEyeHeight() {
|
||||
return eyeHeight;
|
||||
}
|
||||
|
||||
public void setEyeHeight(Float eyeHeight) {
|
||||
if (eyeHeight < this.height) {
|
||||
this.eyeHeight = eyeHeight;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasEnteredUsername() {
|
||||
return hasEnteredUsername;
|
||||
}
|
||||
|
||||
public void setHasEnteredUsername(boolean entered) {
|
||||
this.hasEnteredUsername = entered;
|
||||
}
|
||||
|
||||
public void setDiscordPresence(boolean discordPresence) {
|
||||
boolean oldValue = this.discordPresence;
|
||||
this.discordPresence = discordPresence;
|
||||
propertyChangeSupport.firePropertyChange(DISCORD_PRESENCE, oldValue, discordPresence);
|
||||
}
|
||||
|
||||
public boolean isDiscordPresence() {
|
||||
return discordPresence;
|
||||
}
|
||||
public final Setting<String> playerName = setting(
|
||||
type(String.class),
|
||||
defaultValue(defaultPlayerName()),
|
||||
name("${engine:menu#player-name}"),
|
||||
constraint(new StringConstraint(
|
||||
StringConstraint.notEmptyOrNull(),
|
||||
StringConstraint.maxLength(100))
|
||||
)
|
||||
);
|
||||
public final Setting<Color> color = setting(
|
||||
type(Color.class),
|
||||
defaultValue(defaultPlayerColor()),
|
||||
name("${engine:menu#player-color}"),
|
||||
constraint(new ColorConstraint())
|
||||
);
|
||||
public final Setting<Float> height = setting(
|
||||
type(Float.class),
|
||||
defaultValue(DEFAULT_PLAYER_HEIGHT),
|
||||
name("${engine:menu#player-height}"),
|
||||
constraint(new NumberRangeConstraint<>(1.5f, 2.0f, true, true))
|
||||
);
|
||||
public final Setting<Float> eyeHeight = setting(
|
||||
type(Float.class),
|
||||
defaultValue(DEFAULT_PLAYER_EYE_HEIGHT),
|
||||
name("${engine:menu#player-eye-height}"),
|
||||
constraint(new NumberRangeConstraint<>(0.5f, 1.5f, true, true))
|
||||
);
|
||||
|
||||
/**
|
||||
* Generates the player's default name. The default name is the string "Player" followed by a random 5 digit code ranging from 10000 to 99999.
|
||||
* Generates the player's default name. The default name is the string "Player" followed by a random 5 digit code
|
||||
* ranging from 10000 to 99999.
|
||||
*
|
||||
* @return a String with the player's default name.
|
||||
*/
|
||||
|
@ -120,4 +74,9 @@ public class PlayerConfig extends AbstractSubscribable {
|
|||
List<Color> colors = CieCamColors.L65C65;
|
||||
return colors.get(rng.nextInt(colors.size()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "${engine:menu#player-settings-title}";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,18 +1,5 @@
|
|||
/*
|
||||
* Copyright 2015 MovingBlocks
|
||||
*
|
||||
* Licensed 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.
|
||||
*/
|
||||
// Copyright 2021 The Terasology Foundation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package org.terasology.engine.config;
|
||||
|
||||
|
@ -27,7 +14,6 @@ import java.util.Map;
|
|||
* and loaded in a JSON format.
|
||||
*/
|
||||
public final class RootConfig {
|
||||
private PlayerConfig player = new PlayerConfig();
|
||||
private PermissionConfig permission = new PermissionConfig();
|
||||
private InputConfig input = new InputConfig();
|
||||
private BindsConfig binds = new BindsConfig();
|
||||
|
@ -70,10 +56,6 @@ public final class RootConfig {
|
|||
return network;
|
||||
}
|
||||
|
||||
public PlayerConfig getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
public RenderingConfig getRendering() {
|
||||
return rendering;
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ package org.terasology.engine.config;
|
|||
|
||||
import org.terasology.engine.config.flexible.AutoConfig;
|
||||
import org.terasology.engine.config.flexible.Setting;
|
||||
import org.terasology.engine.config.flexible.constraints.LocaleConstraint;
|
||||
import org.terasology.engine.config.flexible.constraints.NumberRangeConstraint;
|
||||
|
||||
import java.util.Locale;
|
||||
|
@ -13,6 +14,7 @@ import java.util.Optional;
|
|||
|
||||
import static org.terasology.engine.config.flexible.SettingArgument.constraint;
|
||||
import static org.terasology.engine.config.flexible.SettingArgument.defaultValue;
|
||||
import static org.terasology.engine.config.flexible.SettingArgument.name;
|
||||
import static org.terasology.engine.config.flexible.SettingArgument.override;
|
||||
import static org.terasology.engine.config.flexible.SettingArgument.type;
|
||||
|
||||
|
@ -23,40 +25,47 @@ public class SystemConfig extends AutoConfig {
|
|||
public final Setting<Long> dayNightLengthInMs = setting(
|
||||
type(Long.class),
|
||||
defaultValue(1800000L),
|
||||
name("Day/Night length (ms) (not yet)"),
|
||||
constraint(new NumberRangeConstraint<>(0L, Long.MAX_VALUE, false, false))
|
||||
);
|
||||
|
||||
public final Setting<Integer> maxThreads = setting(
|
||||
type(Integer.class),
|
||||
defaultValue(Runtime.getRuntime().availableProcessors() - 1),
|
||||
name("Max threads(not yet)"),
|
||||
constraint(new NumberRangeConstraint<>(0, Integer.MAX_VALUE, false, false))
|
||||
);
|
||||
|
||||
public final Setting<Integer> maxSecondsBetweenSaves = setting(
|
||||
type(Integer.class),
|
||||
defaultValue(60),
|
||||
constraint(new NumberRangeConstraint<>(0, Integer.MAX_VALUE, false, false))
|
||||
name("Seconds between saves"),
|
||||
constraint(new NumberRangeConstraint<>(0, 1200, false, false))
|
||||
);
|
||||
|
||||
public final Setting<Integer> maxUnloadedChunksPercentageTillSave = setting(
|
||||
type(Integer.class),
|
||||
defaultValue(40),
|
||||
name("Max unloaded chunks percentage till save"),
|
||||
constraint(new NumberRangeConstraint<>(0, 100, false, false))
|
||||
);
|
||||
|
||||
public final Setting<Boolean> debugEnabled = setting(
|
||||
type(Boolean.class),
|
||||
defaultValue(false)
|
||||
defaultValue(false),
|
||||
name("Debug mode")
|
||||
);
|
||||
|
||||
public final Setting<Boolean> monitoringEnabled = setting(
|
||||
type(Boolean.class),
|
||||
defaultValue(false)
|
||||
defaultValue(false),
|
||||
name("Monitoring")
|
||||
);
|
||||
|
||||
public final Setting<Boolean> writeSaveGamesEnabled = setting(
|
||||
type(Boolean.class),
|
||||
defaultValue(true),
|
||||
name("Game saves"),
|
||||
override(() -> Optional.ofNullable(
|
||||
System.getProperty(SAVED_GAMES_ENABLED_PROPERTY))
|
||||
.map(Boolean::parseBoolean))
|
||||
|
@ -65,12 +74,15 @@ public class SystemConfig extends AutoConfig {
|
|||
public final Setting<Long> chunkGenerationFailTimeoutInMs = setting(
|
||||
type(Long.class),
|
||||
defaultValue(1800000L),
|
||||
constraint(new NumberRangeConstraint<>(0L, Long.MAX_VALUE, false, false))
|
||||
name("Chunk generation fail timeout (ms)"),
|
||||
constraint(new NumberRangeConstraint<>(0L, 3600000L, false, false))
|
||||
);
|
||||
|
||||
public final Setting<Locale> locale = setting(
|
||||
type(Locale.class),
|
||||
defaultValue(Locale.getDefault(Category.DISPLAY))
|
||||
defaultValue(Locale.getDefault(Category.DISPLAY)),
|
||||
name("${engine:menu#settings-language}"),
|
||||
constraint(new LocaleConstraint(Locale.getAvailableLocales())) // TODO provide translate project's locales (Pirate lang don't works)
|
||||
);
|
||||
|
||||
@Override
|
||||
|
|
|
@ -32,7 +32,7 @@ import java.util.Set;
|
|||
public class AutoConfigManager {
|
||||
private static final Logger logger = LoggerFactory.getLogger(AutoConfigManager.class);
|
||||
|
||||
private final Set<AutoConfig> loadedConfigs = Sets.newHashSet();
|
||||
private final Set<AutoConfig> loadedConfigs = Sets.newLinkedHashSet();
|
||||
private final Serializer<?> serializer;
|
||||
|
||||
public AutoConfigManager(Serializer<?> serializer) {
|
||||
|
@ -109,7 +109,7 @@ public class AutoConfigManager {
|
|||
// TODO: Save when screen for config closed
|
||||
Path configPath = getConfigPath(config.getId());
|
||||
try (OutputStream output = Files.newOutputStream(configPath, StandardOpenOption.CREATE)) {
|
||||
serializer.serialize(config, TypeInfo.of(AutoConfig.class), output);
|
||||
serializer.serialize(config, TypeInfo.of((Class<AutoConfig>)config.getClass()), output);
|
||||
} catch (IOException e) {
|
||||
logger.error("Error while saving config {} to disk", config.getId(), e);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
// Copyright 2021 The Terasology Foundation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package org.terasology.engine.config.flexible.bindings;
|
||||
|
||||
import org.terasology.nui.databinding.Binding;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
public class MappingBinding<T, R> implements Binding<T> {
|
||||
private final Binding<R> internalBinging;
|
||||
private final Function<T, R> setMapping;
|
||||
private final Function<R, T> getMapping;
|
||||
|
||||
public MappingBinding(Binding<R> internalBinging, Function<T, R> setMapping, Function<R, T> getMapping) {
|
||||
this.internalBinging = internalBinging;
|
||||
this.setMapping = setMapping;
|
||||
this.getMapping = getMapping;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T get() {
|
||||
return getMapping.apply(internalBinging.get());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(T value) {
|
||||
internalBinging.set(setMapping.apply(value));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
// Copyright 2021 The Terasology Foundation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package org.terasology.engine.config.flexible.bindings;
|
||||
|
||||
|
||||
import org.terasology.engine.config.flexible.Setting;
|
||||
import org.terasology.nui.databinding.Binding;
|
||||
|
||||
public class SettingBinding<T> implements Binding<T> {
|
||||
private final Setting<T> setting;
|
||||
|
||||
public SettingBinding(Setting<T> setting) {
|
||||
this.setting = setting;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public T get() {
|
||||
return setting.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(T value) {
|
||||
setting.set(value);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
// Copyright 2021 The Terasology Foundation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package org.terasology.engine.config.flexible.constraints;
|
||||
|
||||
import org.terasology.nui.Color;
|
||||
|
||||
public class ColorConstraint implements SettingConstraint<Color> {
|
||||
|
||||
@Override
|
||||
public boolean isSatisfiedBy(Color value) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void warnUnsatisfiedBy(Color value) {
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
// Copyright 2021 The Terasology Foundation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package org.terasology.engine.config.flexible.constraints;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class LocaleConstraint implements SettingConstraint<Locale> {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(LocaleConstraint.class);
|
||||
|
||||
private final Set<Locale> locales;
|
||||
|
||||
public LocaleConstraint(Set<Locale> locales) {
|
||||
this.locales = locales;
|
||||
}
|
||||
|
||||
public LocaleConstraint(Locale... locales) {
|
||||
this.locales = Sets.newHashSet(locales);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSatisfiedBy(Locale value) {
|
||||
return locales.contains(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void warnUnsatisfiedBy(Locale value) {
|
||||
logger.warn("Locale {} should be one of {}",
|
||||
value,
|
||||
locales.stream()
|
||||
.map(Locale::getLanguage)
|
||||
.collect(Collectors.joining(",", "[", "]"))
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
// Copyright 2021 The Terasology Foundation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package org.terasology.engine.config.flexible.constraints;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class PredicateWithDescription<T> implements Predicate<T> {
|
||||
private final Predicate<T> predicate;
|
||||
private final String description;
|
||||
|
||||
public PredicateWithDescription(String description, Predicate<T> predicate) {
|
||||
this.predicate = predicate;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(T s) {
|
||||
return predicate.test(s);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
// Copyright 2021 The Terasology Foundation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package org.terasology.engine.config.flexible.constraints;
|
||||
|
||||
import com.google.common.base.Predicates;
|
||||
import com.google.common.base.Strings;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class StringConstraint implements SettingConstraint<String> {
|
||||
private static final Logger logger = LoggerFactory.getLogger(StringConstraint.class);
|
||||
private final List<Predicate<String>> predicates;
|
||||
|
||||
public StringConstraint(Predicate<String>... predicates) {
|
||||
this.predicates = Arrays.asList(predicates);
|
||||
}
|
||||
|
||||
public static Predicate<String> notEmptyOrNull() {
|
||||
return new PredicateWithDescription<>("not null or not empty", Predicates.not(Strings::isNullOrEmpty));
|
||||
}
|
||||
|
||||
public static Predicate<String> maxLength(int length) {
|
||||
return new PredicateWithDescription<>("length should be less than " + length, s -> s.length() < length);
|
||||
}
|
||||
|
||||
public static Predicate<String> regex(String regex) {
|
||||
Pattern pattern = Pattern.compile(regex);
|
||||
return new PredicateWithDescription<>("matches regex: \"" + regex + "\"", s -> pattern.matcher(s).matches());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String getDescription(Predicate<String> p) {
|
||||
if (p instanceof PredicateWithDescription) {
|
||||
return ((PredicateWithDescription<String>) p).getDescription();
|
||||
} else {
|
||||
return "Predicate without description";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSatisfiedBy(String value) {
|
||||
return predicates.stream().allMatch(p -> p.test(value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void warnUnsatisfiedBy(String value) {
|
||||
logger.warn("String [{}] does not match the conditions: {}", value,
|
||||
predicates.stream()
|
||||
.filter(p -> !p.test(value))
|
||||
.map(StringConstraint::getDescription)
|
||||
.collect(Collectors.joining(",", "[", "]")));
|
||||
}
|
||||
}
|
|
@ -9,14 +9,14 @@ import org.terasology.gestalt.assets.management.AssetManager;
|
|||
import org.terasology.engine.config.flexible.AutoConfig;
|
||||
import org.terasology.engine.config.flexible.AutoConfigManager;
|
||||
import org.terasology.engine.core.module.ModuleManager;
|
||||
import org.terasology.engine.registry.In;
|
||||
import org.terasology.engine.rendering.nui.CoreScreenLayer;
|
||||
import org.terasology.nui.UIWidget;
|
||||
import org.terasology.nui.WidgetUtil;
|
||||
import org.terasology.nui.databinding.Binding;
|
||||
import org.terasology.nui.databinding.DefaultBinding;
|
||||
import org.terasology.nui.layouts.ColumnLayout;
|
||||
import org.terasology.nui.widgets.types.TypeWidgetLibrary;
|
||||
import org.terasology.engine.registry.In;
|
||||
import org.terasology.engine.rendering.nui.CoreScreenLayer;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
|
@ -46,7 +46,7 @@ public class AutoConfigScreen extends CoreScreenLayer {
|
|||
if (widget.isPresent()) {
|
||||
mainContainer.addWidget(widget.get());
|
||||
} else {
|
||||
logger.warn("Cannot create widget for config:{}", config.getId());
|
||||
logger.warn("Cannot create widget for config: {}", config.getId());
|
||||
}
|
||||
}
|
||||
WidgetUtil.trySubscribe(this, "close", button -> triggerBackAnimation());
|
||||
|
|
|
@ -6,6 +6,7 @@ import org.slf4j.Logger;
|
|||
import org.slf4j.LoggerFactory;
|
||||
import org.terasology.engine.config.flexible.AutoConfig;
|
||||
import org.terasology.engine.config.flexible.Setting;
|
||||
import org.terasology.engine.context.Context;
|
||||
import org.terasology.engine.core.module.ModuleManager;
|
||||
import org.terasology.engine.i18n.TranslationSystem;
|
||||
import org.terasology.engine.registry.In;
|
||||
|
@ -54,8 +55,11 @@ public class AutoConfigWidgetFactory implements TypeWidgetFactory {
|
|||
@In
|
||||
private TranslationSystem translationSystem;
|
||||
|
||||
public AutoConfigWidgetFactory(ModuleManager moduleManager, AssetManager assetManager) {
|
||||
this.settingWidgetFactory = new SettingWidgetFactory(moduleManager.getEnvironment(), assetManager);
|
||||
public AutoConfigWidgetFactory(ModuleManager moduleManager,
|
||||
AssetManager assetManager,
|
||||
Context context) {
|
||||
this.settingWidgetFactory =
|
||||
new SettingWidgetFactory(moduleManager.getEnvironment(), assetManager, context);
|
||||
this.assetManager = assetManager;
|
||||
}
|
||||
|
||||
|
@ -75,7 +79,7 @@ public class AutoConfigWidgetFactory implements TypeWidgetFactory {
|
|||
Optional<UIWidget> settingWidget = settingWidgetFactory.createWidgetFor(setting);
|
||||
|
||||
if (!settingWidget.isPresent()) {
|
||||
logger.error("Couldn't find a widget for the Setting");
|
||||
logger.error("Couldn't find a widget for the Setting [{}]", setting.getHumanReadableName());
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
// Copyright 2021 The Terasology Foundation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package org.terasology.engine.config.flexible.ui;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Functions;
|
||||
import com.google.common.math.DoubleMath;
|
||||
import org.terasology.gestalt.assets.ResourceUrn;
|
||||
import org.terasology.gestalt.assets.management.AssetManager;
|
||||
import org.terasology.engine.config.flexible.bindings.MappingBinding;
|
||||
import org.terasology.engine.config.flexible.bindings.SettingBinding;
|
||||
import org.terasology.engine.config.flexible.constraints.ColorConstraint;
|
||||
import org.terasology.engine.registry.In;
|
||||
import org.terasology.engine.rendering.assets.texture.Texture;
|
||||
import org.terasology.engine.rendering.assets.texture.TextureUtil;
|
||||
import org.terasology.engine.rendering.nui.layers.mainMenu.settings.CieCamColors;
|
||||
import org.terasology.nui.Color;
|
||||
import org.terasology.nui.UIWidget;
|
||||
import org.terasology.nui.widgets.UIImage;
|
||||
import org.terasology.nui.widgets.UISlider;
|
||||
|
||||
import java.math.RoundingMode;
|
||||
import java.util.List;
|
||||
|
||||
public class ColorConstraintWidgetFactory extends AssetBackedConstraintWidgetFactory<Color, ColorConstraint> {
|
||||
|
||||
@In
|
||||
private AssetManager assetManager;
|
||||
|
||||
private final List<Color> colors = CieCamColors.L65C65;
|
||||
|
||||
public ColorConstraintWidgetFactory() {
|
||||
super("engine:colorPickerWidget");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void bindWidgetToSetting(UIWidget widget) {
|
||||
UIImage img = widget.find("image", UIImage.class);
|
||||
if (img != null) {
|
||||
ResourceUrn uri = TextureUtil.getTextureUriForColor(Color.WHITE);
|
||||
Texture tex = assetManager.getAsset(uri, Texture.class).get();
|
||||
img.setImage(tex);
|
||||
img.bindTint(new SettingBinding<>(getSetting()));
|
||||
}
|
||||
|
||||
UISlider slider = widget.find("tone", UISlider.class);
|
||||
slider.setIncrement(0.01f);
|
||||
Function<Object, String> constant = Functions.constant(" "); // ensure a certain width
|
||||
slider.setLabelFunction(constant);
|
||||
|
||||
slider.bindValue(
|
||||
new MappingBinding<>(
|
||||
new SettingBinding<>(getSetting()),
|
||||
this::findClosestColor,
|
||||
this::findClosestIndex
|
||||
));
|
||||
}
|
||||
|
||||
private float findClosestIndex(Color color) {
|
||||
int best = 0;
|
||||
float minDist = Float.MAX_VALUE;
|
||||
for (int i = 0; i < colors.size(); i++) {
|
||||
Color other = colors.get(i);
|
||||
float dr = other.rf() - color.rf();
|
||||
float dg = other.gf() - color.gf();
|
||||
float db = other.bf() - color.bf();
|
||||
|
||||
// there are certainly smarter ways to measure color distance,
|
||||
// but Euclidean distance is good enough for the purpose
|
||||
float dist = dr * dr + dg * dg + db * db;
|
||||
if (dist < minDist) {
|
||||
minDist = dist;
|
||||
best = i;
|
||||
}
|
||||
}
|
||||
|
||||
float max = colors.size() - 1;
|
||||
return best / max;
|
||||
}
|
||||
|
||||
private Color findClosestColor(float findex) {
|
||||
int index = DoubleMath.roundToInt(findex * (double) (colors.size() - 1), RoundingMode.HALF_UP);
|
||||
Color color = colors.get(index);
|
||||
return color;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
// Copyright 2021 The Terasology Foundation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package org.terasology.engine.config.flexible.ui;
|
||||
|
||||
import org.terasology.engine.config.flexible.Setting;
|
||||
import org.terasology.engine.config.flexible.constraints.SettingConstraint;
|
||||
import org.terasology.engine.context.Context;
|
||||
import org.terasology.nui.UIWidget;
|
||||
import org.terasology.nui.databinding.Binding;
|
||||
import org.terasology.nui.widgets.types.TypeWidgetLibrary;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class DefaultConstraintWidgetFactory<T> extends ConstraintWidgetFactory<T, SettingConstraint<T>> {
|
||||
private final Context context;
|
||||
|
||||
public DefaultConstraintWidgetFactory(Context context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Optional<UIWidget> buildWidget() {
|
||||
Setting<T> setting = getSetting();
|
||||
Binding<T> binding = new Binding<T>() {
|
||||
@Override
|
||||
public T get() {
|
||||
return setting.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(T value) {
|
||||
setting.set(value);
|
||||
}
|
||||
};
|
||||
return context.get(TypeWidgetLibrary.class).getWidget(binding, setting.getValueType());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
// Copyright 2021 The Terasology Foundation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package org.terasology.engine.config.flexible.ui;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import org.terasology.engine.config.flexible.Setting;
|
||||
import org.terasology.engine.config.flexible.constraints.LocaleConstraint;
|
||||
import org.terasology.engine.core.SimpleUri;
|
||||
import org.terasology.engine.i18n.TranslationProject;
|
||||
import org.terasology.engine.i18n.TranslationSystem;
|
||||
import org.terasology.engine.rendering.nui.layers.mainMenu.settings.LocaleRenderer;
|
||||
import org.terasology.nui.UIWidget;
|
||||
import org.terasology.nui.databinding.Binding;
|
||||
import org.terasology.nui.widgets.UIDropdownScrollable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class LocaleConstraintWidgetFactory extends ConstraintWidgetFactory<Locale, LocaleConstraint> {
|
||||
|
||||
/**
|
||||
* Remove language x from this languagesExcluded table when it is ready for testing
|
||||
*/
|
||||
private final Locale[] languagesExcluded =
|
||||
{Locale.forLanguageTag("zh"), // TODO: Chinese symbols not yet available
|
||||
Locale.forLanguageTag("hi"), // TODO: Hindi (Indian) symbols not yet available
|
||||
Locale.forLanguageTag("ar"), // TODO: Arabic symbols not yet available, no translated entries yet
|
||||
Locale.forLanguageTag("ko"), // TODO: Korean symbols not yet available
|
||||
Locale.forLanguageTag("fa")}; // TODO: Farsi (Persian) symbols not yet available
|
||||
|
||||
|
||||
private final TranslationSystem translationSystem;
|
||||
|
||||
public LocaleConstraintWidgetFactory(TranslationSystem translationSystem) {
|
||||
this.translationSystem = translationSystem;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Optional<UIWidget> buildWidget() {
|
||||
Setting<Locale> setting = getSetting();
|
||||
|
||||
Binding<Locale> binding = new Binding<Locale>() {
|
||||
@Override
|
||||
public Locale get() {
|
||||
return setting.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(Locale value) {
|
||||
setting.set(value);
|
||||
}
|
||||
};
|
||||
|
||||
UIDropdownScrollable<Locale> dropdownScrollable = new UIDropdownScrollable<>();
|
||||
SimpleUri menuUri = new SimpleUri("engine:menu");
|
||||
TranslationProject menuProject = translationSystem.getProject(menuUri);
|
||||
List<Locale> locales = new ArrayList<>(menuProject.getAvailableLocales());
|
||||
for (Locale languageExcluded : languagesExcluded) {
|
||||
locales.remove(languageExcluded);
|
||||
}
|
||||
Collections.sort(locales, (Comparator.comparing((Function<Object, String>) Object::toString)));
|
||||
dropdownScrollable.setOptions(Lists.newArrayList(locales));
|
||||
dropdownScrollable.setVisibleOptions(5); // Set maximum number of options visible for scrolling
|
||||
dropdownScrollable.bindSelection(binding);
|
||||
|
||||
dropdownScrollable.setOptionRenderer(new LocaleRenderer(translationSystem));
|
||||
|
||||
return Optional.of(dropdownScrollable);
|
||||
}
|
||||
}
|
|
@ -1,16 +1,17 @@
|
|||
// Copyright 2020 The Terasology Foundation
|
||||
// Copyright 2021 The Terasology Foundation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
package org.terasology.engine.config.flexible.ui;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import org.terasology.gestalt.assets.management.AssetManager;
|
||||
import org.terasology.engine.config.flexible.Setting;
|
||||
import org.terasology.engine.config.flexible.constraints.SettingConstraint;
|
||||
import org.terasology.gestalt.module.ModuleEnvironment;
|
||||
import org.terasology.nui.UIWidget;
|
||||
import org.terasology.engine.context.Context;
|
||||
import org.terasology.engine.registry.In;
|
||||
import org.terasology.engine.registry.InjectionHelper;
|
||||
import org.terasology.engine.utilities.ReflectionUtil;
|
||||
import org.terasology.gestalt.assets.management.AssetManager;
|
||||
import org.terasology.gestalt.module.ModuleEnvironment;
|
||||
import org.terasology.nui.UIWidget;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Optional;
|
||||
|
@ -29,10 +30,12 @@ import java.util.Optional;
|
|||
public class SettingWidgetFactory {
|
||||
private final ModuleEnvironment environment;
|
||||
private final AssetManager assetManager;
|
||||
private final Context context;
|
||||
|
||||
public SettingWidgetFactory(ModuleEnvironment environment, AssetManager assetManager) {
|
||||
public SettingWidgetFactory(ModuleEnvironment environment, AssetManager assetManager, Context context) {
|
||||
this.environment = environment;
|
||||
this.assetManager = assetManager;
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -43,7 +46,8 @@ public class SettingWidgetFactory {
|
|||
*/
|
||||
public <T> Optional<UIWidget> createWidgetFor(Setting<T> setting) {
|
||||
return getConstraintWidgetFactory(setting)
|
||||
.flatMap(factory -> factory.buildWidgetFor(setting));
|
||||
.orElseGet(()-> new DefaultConstraintWidgetFactory<>(context))
|
||||
.buildWidgetFor(setting);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -55,22 +59,23 @@ public class SettingWidgetFactory {
|
|||
*/
|
||||
<T> Optional<ConstraintWidgetFactory<T, ?>> getConstraintWidgetFactory(Setting<T> setting) {
|
||||
SettingConstraint<?> constraint = setting.getConstraint();
|
||||
if (constraint != null) {
|
||||
for (Class<? extends ConstraintWidgetFactory> widgetType
|
||||
: environment.getSubtypesOf(ConstraintWidgetFactory.class)) {
|
||||
Type constraintType =
|
||||
ReflectionUtil.getTypeParameterForSuper(widgetType, ConstraintWidgetFactory.class, 1);
|
||||
|
||||
for (Class<? extends ConstraintWidgetFactory> widgetType : environment.getSubtypesOf(ConstraintWidgetFactory.class)) {
|
||||
Type constraintType =
|
||||
ReflectionUtil.getTypeParameterForSuper(widgetType, ConstraintWidgetFactory.class, 1);
|
||||
if (constraint.getClass().equals(ReflectionUtil.getRawType(constraintType))) {
|
||||
|
||||
if (constraint.getClass().equals(ReflectionUtil.getRawType(constraintType))) {
|
||||
try {
|
||||
ConstraintWidgetFactory<T, ?> factory = widgetType.newInstance();
|
||||
ConstraintWidgetFactory<T, ?> factory =
|
||||
InjectionHelper.createWithConstructorInjection(widgetType, context);
|
||||
InjectionHelper.inject(factory, In.class, ImmutableMap.of(AssetManager.class, assetManager));
|
||||
|
||||
return Optional.of(factory);
|
||||
} catch (InstantiationException | IllegalAccessException ignored) { }
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Optional.empty();
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,22 +1,8 @@
|
|||
/*
|
||||
* Copyright 2013 MovingBlocks
|
||||
*
|
||||
* Licensed 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.
|
||||
*/
|
||||
// Copyright 2021 The Terasology Foundation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package org.terasology.engine.core.modes.loadProcesses;
|
||||
|
||||
import org.terasology.engine.config.Config;
|
||||
import org.terasology.engine.config.PlayerConfig;
|
||||
import org.terasology.engine.context.Context;
|
||||
import org.terasology.engine.core.modes.SingleStepLoadProcess;
|
||||
|
@ -41,8 +27,9 @@ public class SetupLocalPlayer extends SingleStepLoadProcess {
|
|||
|
||||
@Override
|
||||
public boolean step() {
|
||||
PlayerConfig playerConfig = context.get(Config.class).getPlayer();
|
||||
Client localClient = context.get(NetworkSystem.class).joinLocal(playerConfig.getName(), playerConfig.getColor());
|
||||
PlayerConfig playerConfig = context.get(PlayerConfig.class);
|
||||
Client localClient = context.get(NetworkSystem.class).joinLocal(playerConfig.playerName.get(),
|
||||
playerConfig.color.get());
|
||||
context.get(LocalPlayer.class).setClientEntity(localClient.getEntity());
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -25,8 +25,7 @@ import java.util.concurrent.CopyOnWriteArrayList;
|
|||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* A translation system that uses {@link Translation} data assets to
|
||||
* perform the lookup.
|
||||
* A translation system that uses {@link Translation} data assets to perform the lookup.
|
||||
*/
|
||||
public class TranslationSystemImpl implements TranslationSystem {
|
||||
|
||||
|
@ -46,7 +45,6 @@ public class TranslationSystemImpl implements TranslationSystem {
|
|||
|
||||
systemConfig = context.get(SystemConfig.class);
|
||||
assetManager = context.get(AssetManager.class);
|
||||
|
||||
refresh();
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ package org.terasology.engine.logic.characters;
|
|||
import org.joml.Quaternionf;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.terasology.engine.config.Config;
|
||||
import org.terasology.engine.config.PlayerConfig;
|
||||
import org.terasology.engine.entitySystem.entity.EntityBuilder;
|
||||
import org.terasology.engine.entitySystem.entity.EntityManager;
|
||||
import org.terasology.engine.entitySystem.entity.EntityRef;
|
||||
|
@ -32,7 +32,7 @@ public class GazeAuthoritySystem extends BaseComponentSystem {
|
|||
@In
|
||||
EntityManager entityManager;
|
||||
@In
|
||||
private Config config;
|
||||
private PlayerConfig playerConfig;
|
||||
|
||||
@ReceiveEvent
|
||||
public void ensureGazeContainerEntitiesCreated(OnActivatedComponent event, EntityRef entityRef, GazeMountPointComponent gazeMountPointComponent,
|
||||
|
@ -41,7 +41,7 @@ public class GazeAuthoritySystem extends BaseComponentSystem {
|
|||
gazeMountPointComponent.gazeEntity = createGazeEntity();
|
||||
entityRef.saveComponent(gazeMountPointComponent);
|
||||
}
|
||||
gazeMountPointComponent.translate.y = config.getPlayer().getEyeHeight();
|
||||
gazeMountPointComponent.translate.y = playerConfig.eyeHeight.get();
|
||||
Location.attachChild(entityRef, gazeMountPointComponent.gazeEntity, gazeMountPointComponent.translate, new Quaternionf());
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ import org.joml.Matrix4f;
|
|||
import org.joml.Quaternionf;
|
||||
import org.joml.Vector3f;
|
||||
import org.terasology.engine.config.Config;
|
||||
import org.terasology.engine.config.PlayerConfig;
|
||||
import org.terasology.engine.core.SimpleUri;
|
||||
import org.terasology.engine.core.Time;
|
||||
import org.terasology.engine.core.subsystem.config.BindsManager;
|
||||
|
@ -87,6 +88,8 @@ public class LocalPlayerSystem extends BaseComponentSystem implements UpdateSubs
|
|||
@In
|
||||
private Config config;
|
||||
@In
|
||||
private PlayerConfig playerConfig;
|
||||
@In
|
||||
private InputSystem inputSystem;
|
||||
|
||||
@In
|
||||
|
@ -224,7 +227,7 @@ public class LocalPlayerSystem extends BaseComponentSystem implements UpdateSubs
|
|||
public void onPlayerSpawn(OnPlayerSpawnedEvent event, EntityRef character) {
|
||||
if (character.equals(localPlayer.getCharacterEntity())) {
|
||||
// update character height as given in player settings
|
||||
ScaleToRequest scaleRequest = new ScaleToRequest(config.getPlayer().getHeight());
|
||||
ScaleToRequest scaleRequest = new ScaleToRequest(playerConfig.height.get());
|
||||
localPlayer.getCharacterEntity().send(scaleRequest);
|
||||
|
||||
// Trigger updating the player camera position as soon as the local player is spawned.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2020 The Terasology Foundation
|
||||
// Copyright 2021 The Terasology Foundation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
package org.terasology.engine.network.internal;
|
||||
|
||||
|
@ -9,6 +9,7 @@ import io.netty.channel.ChannelInboundHandlerAdapter;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.terasology.engine.config.Config;
|
||||
import org.terasology.engine.config.PlayerConfig;
|
||||
import org.terasology.engine.core.EngineTime;
|
||||
import org.terasology.engine.core.Time;
|
||||
import org.terasology.engine.core.module.ModuleManager;
|
||||
|
@ -289,12 +290,13 @@ public class ClientConnectionHandler extends ChannelInboundHandlerAdapter {
|
|||
*/
|
||||
private void sendJoin(ChannelHandlerContext channelHandlerContext) {
|
||||
Config config = CoreRegistry.get(Config.class);
|
||||
PlayerConfig playerConfig = CoreRegistry.get(PlayerConfig.class);
|
||||
NetData.JoinMessage.Builder bldr = NetData.JoinMessage.newBuilder();
|
||||
NetData.Color.Builder clrbldr = NetData.Color.newBuilder();
|
||||
|
||||
bldr.setName(config.getPlayer().getName());
|
||||
bldr.setName(playerConfig.playerName.get());
|
||||
bldr.setViewDistanceLevel(config.getRendering().getViewDistance().getIndex());
|
||||
bldr.setColor(clrbldr.setRgba(config.getPlayer().getColor().rgba()).build());
|
||||
bldr.setColor(clrbldr.setRgba(playerConfig.color.get().rgba()).build());
|
||||
|
||||
channelHandlerContext.channel().writeAndFlush(NetData.NetMessage.newBuilder().setJoin(bldr).build());
|
||||
}
|
||||
|
|
|
@ -4,33 +4,30 @@ package org.terasology.engine.rendering.nui.layers.mainMenu;
|
|||
|
||||
import com.google.common.base.Strings;
|
||||
import org.terasology.gestalt.assets.ResourceUrn;
|
||||
import org.terasology.engine.config.Config;
|
||||
import org.terasology.engine.config.PlayerConfig;
|
||||
import org.terasology.engine.i18n.TranslationSystem;
|
||||
import org.terasology.engine.registry.In;
|
||||
import org.terasology.engine.rendering.nui.CoreScreenLayer;
|
||||
import org.terasology.nui.WidgetUtil;
|
||||
import org.terasology.nui.databinding.ReadOnlyBinding;
|
||||
import org.terasology.nui.widgets.UIButton;
|
||||
import org.terasology.nui.widgets.UIText;
|
||||
import org.terasology.engine.registry.In;
|
||||
import org.terasology.engine.rendering.nui.CoreScreenLayer;
|
||||
|
||||
public class EnterUsernamePopup extends CoreScreenLayer {
|
||||
public static final ResourceUrn ASSET_URI = new ResourceUrn("engine:enterUsernamePopup");
|
||||
|
||||
@In
|
||||
private Config config;
|
||||
@In
|
||||
private TranslationSystem translationSystem;
|
||||
@In
|
||||
private PlayerConfig playerConfig;
|
||||
|
||||
private UIText username;
|
||||
private PlayerConfig playerConfig;
|
||||
|
||||
@Override
|
||||
public void initialise() {
|
||||
playerConfig = config.getPlayer();
|
||||
|
||||
username = find("username", UIText.class);
|
||||
username.setText(playerConfig.getName());
|
||||
username.setText(playerConfig.playerName.get());
|
||||
username.bindTooltipString(new ReadOnlyBinding<String>() {
|
||||
@Override
|
||||
public String get() {
|
||||
|
@ -41,8 +38,7 @@ public class EnterUsernamePopup extends CoreScreenLayer {
|
|||
UIButton okButton = find("ok", UIButton.class);
|
||||
if (okButton != null) {
|
||||
okButton.subscribe(button -> {
|
||||
playerConfig.setName(username.getText().trim());
|
||||
playerConfig.setHasEnteredUsername(true);
|
||||
playerConfig.playerName.set(username.getText().trim());
|
||||
getManager().popScreen();
|
||||
});
|
||||
okButton.bindEnabled(new ReadOnlyBinding<Boolean>() {
|
||||
|
@ -61,7 +57,6 @@ public class EnterUsernamePopup extends CoreScreenLayer {
|
|||
}
|
||||
|
||||
WidgetUtil.trySubscribe(this, "cancel", button -> {
|
||||
playerConfig.setHasEnteredUsername(true);
|
||||
getManager().popScreen();
|
||||
});
|
||||
}
|
||||
|
@ -70,7 +65,7 @@ public class EnterUsernamePopup extends CoreScreenLayer {
|
|||
public void onOpened() {
|
||||
super.onOpened();
|
||||
if (username != null) {
|
||||
username.setText(config.getPlayer().getName());
|
||||
username.setText(playerConfig.playerName.get());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ import com.google.common.collect.Collections2;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.terasology.engine.config.Config;
|
||||
import org.terasology.engine.config.PlayerConfig;
|
||||
import org.terasology.engine.config.ServerInfo;
|
||||
import org.terasology.engine.core.GameEngine;
|
||||
import org.terasology.engine.core.GameThread;
|
||||
|
@ -62,6 +63,8 @@ public class JoinGameScreen extends CoreScreenLayer {
|
|||
|
||||
@In
|
||||
private Config config;
|
||||
@In
|
||||
private PlayerConfig playerConfig;
|
||||
|
||||
@In
|
||||
private NetworkSystem networkSystem;
|
||||
|
@ -148,7 +151,7 @@ public class JoinGameScreen extends CoreScreenLayer {
|
|||
|
||||
infoService = new ServerInfoService();
|
||||
|
||||
if (!config.getPlayer().hasEnteredUsername()) {
|
||||
if (playerConfig.playerName.getDefaultValue().equals(playerConfig.playerName.get())) {
|
||||
getManager().pushScreen(EnterUsernamePopup.ASSET_URI, EnterUsernamePopup.class);
|
||||
}
|
||||
|
||||
|
|
|
@ -9,15 +9,15 @@ import org.terasology.engine.core.GameEngine;
|
|||
import org.terasology.engine.core.modes.StateLoading;
|
||||
import org.terasology.engine.core.paths.PathManager;
|
||||
import org.terasology.engine.game.GameManifest;
|
||||
import org.terasology.engine.network.NetworkMode;
|
||||
import org.terasology.engine.registry.CoreRegistry;
|
||||
import org.terasology.engine.rendering.nui.animation.MenuAnimationSystems;
|
||||
import org.terasology.engine.rendering.nui.layers.mainMenu.gameDetailsScreen.GameDetailsScreen;
|
||||
import org.terasology.engine.rendering.nui.layers.mainMenu.savedGames.GameInfo;
|
||||
import org.terasology.engine.rendering.nui.layers.mainMenu.savedGames.GameProvider;
|
||||
import org.terasology.engine.network.NetworkMode;
|
||||
import org.terasology.nui.databinding.ReadOnlyBinding;
|
||||
import org.terasology.nui.widgets.UIButton;
|
||||
import org.terasology.nui.widgets.UILabel;
|
||||
import org.terasology.engine.registry.CoreRegistry;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
|
@ -124,7 +124,7 @@ public class SelectGameScreen extends SelectionScreen {
|
|||
triggerForwardAnimation(newGameScreen);
|
||||
}
|
||||
|
||||
if (isLoadingAsServer() && !super.config.getPlayer().hasEnteredUsername()) {
|
||||
if (isLoadingAsServer() && super.playerConfig.playerName.getDefaultValue().equals(super.playerConfig.playerName.get())) {
|
||||
getManager().pushScreen(EnterUsernamePopup.ASSET_URI, EnterUsernamePopup.class);
|
||||
}
|
||||
|
||||
|
|
|
@ -6,25 +6,26 @@ import org.slf4j.Logger;
|
|||
import org.slf4j.LoggerFactory;
|
||||
import org.terasology.gestalt.assets.ResourceUrn;
|
||||
import org.terasology.engine.config.Config;
|
||||
import org.terasology.engine.config.PlayerConfig;
|
||||
import org.terasology.engine.core.TerasologyConstants;
|
||||
import org.terasology.engine.i18n.TranslationSystem;
|
||||
import org.terasology.engine.persistence.internal.GamePreviewImageProvider;
|
||||
import org.terasology.engine.registry.In;
|
||||
import org.terasology.engine.rendering.assets.texture.AWTTextureFormat;
|
||||
import org.terasology.engine.rendering.assets.texture.Texture;
|
||||
import org.terasology.engine.rendering.assets.texture.TextureData;
|
||||
import org.terasology.engine.rendering.nui.CoreScreenLayer;
|
||||
import org.terasology.engine.rendering.nui.layers.mainMenu.savedGames.GameInfo;
|
||||
import org.terasology.engine.utilities.Assets;
|
||||
import org.terasology.engine.utilities.FilesUtil;
|
||||
import org.terasology.engine.world.generator.internal.WorldGeneratorInfo;
|
||||
import org.terasology.engine.world.generator.internal.WorldGeneratorManager;
|
||||
import org.terasology.gestalt.naming.Name;
|
||||
import org.terasology.gestalt.naming.NameVersion;
|
||||
import org.terasology.nui.widgets.UIImage;
|
||||
import org.terasology.nui.widgets.UIImageSlideshow;
|
||||
import org.terasology.nui.widgets.UILabel;
|
||||
import org.terasology.nui.widgets.UIList;
|
||||
import org.terasology.engine.persistence.internal.GamePreviewImageProvider;
|
||||
import org.terasology.engine.registry.In;
|
||||
import org.terasology.engine.rendering.nui.CoreScreenLayer;
|
||||
import org.terasology.engine.utilities.Assets;
|
||||
import org.terasology.engine.utilities.FilesUtil;
|
||||
import org.terasology.engine.world.generator.internal.WorldGeneratorInfo;
|
||||
import org.terasology.engine.world.generator.internal.WorldGeneratorManager;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
|
@ -48,6 +49,9 @@ public abstract class SelectionScreen extends CoreScreenLayer {
|
|||
|
||||
@In
|
||||
protected Config config;
|
||||
@In
|
||||
protected PlayerConfig playerConfig;
|
||||
|
||||
|
||||
@In
|
||||
protected WorldGeneratorManager worldGeneratorManager;
|
||||
|
|
|
@ -2,45 +2,21 @@
|
|||
// SPDX-License-Identifier: Apache-2.0
|
||||
package org.terasology.engine.rendering.nui.layers.mainMenu.settings;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Functions;
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.math.DoubleMath;
|
||||
import org.terasology.gestalt.assets.ResourceUrn;
|
||||
import org.terasology.engine.config.Config;
|
||||
import org.terasology.engine.config.PlayerConfig;
|
||||
import org.terasology.engine.config.SystemConfig;
|
||||
import org.terasology.engine.context.Context;
|
||||
import org.terasology.engine.core.SimpleUri;
|
||||
import org.terasology.engine.i18n.TranslationProject;
|
||||
import org.terasology.engine.i18n.TranslationSystem;
|
||||
import org.terasology.engine.identity.storageServiceClient.StorageServiceWorker;
|
||||
import org.terasology.engine.identity.storageServiceClient.StorageServiceWorkerStatus;
|
||||
import org.terasology.engine.rendering.assets.texture.Texture;
|
||||
import org.terasology.engine.rendering.assets.texture.TextureUtil;
|
||||
import org.terasology.engine.rendering.nui.animation.MenuAnimationSystems;
|
||||
import org.terasology.nui.Color;
|
||||
import org.terasology.nui.WidgetUtil;
|
||||
import org.terasology.nui.databinding.DefaultBinding;
|
||||
import org.terasology.nui.databinding.ReadOnlyBinding;
|
||||
import org.terasology.nui.widgets.UIButton;
|
||||
import org.terasology.nui.widgets.UICheckbox;
|
||||
import org.terasology.nui.widgets.UIDropdownScrollable;
|
||||
import org.terasology.nui.widgets.UIImage;
|
||||
import org.terasology.nui.widgets.UILabel;
|
||||
import org.terasology.nui.widgets.UISlider;
|
||||
import org.terasology.nui.widgets.UIText;
|
||||
import org.terasology.engine.registry.In;
|
||||
import org.terasology.engine.rendering.nui.CoreScreenLayer;
|
||||
import org.terasology.engine.rendering.nui.animation.MenuAnimationSystems;
|
||||
import org.terasology.engine.rendering.nui.layers.mainMenu.StorageServiceLoginPopup;
|
||||
import org.terasology.engine.rendering.nui.layers.mainMenu.ThreeButtonPopup;
|
||||
import org.terasology.engine.utilities.Assets;
|
||||
|
||||
import java.math.RoundingMode;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import org.terasology.nui.WidgetUtil;
|
||||
import org.terasology.nui.widgets.UIButton;
|
||||
import org.terasology.nui.widgets.UILabel;
|
||||
|
||||
import static org.terasology.engine.identity.storageServiceClient.StatusMessageTranslator.getLocalizedButtonMessage;
|
||||
import static org.terasology.engine.identity.storageServiceClient.StatusMessageTranslator.getLocalizedStatusMessage;
|
||||
|
@ -52,7 +28,7 @@ public class PlayerSettingsScreen extends CoreScreenLayer {
|
|||
@In
|
||||
private Context context;
|
||||
@In
|
||||
private Config config;
|
||||
private PlayerConfig config;
|
||||
@In
|
||||
private SystemConfig systemConfig;
|
||||
@In
|
||||
|
@ -60,55 +36,17 @@ public class PlayerSettingsScreen extends CoreScreenLayer {
|
|||
@In
|
||||
private StorageServiceWorker storageService;
|
||||
|
||||
private final List<Color> colors = CieCamColors.L65C65;
|
||||
|
||||
/**
|
||||
* Remove language x from this languagesExcluded table when it is ready for testing
|
||||
*/
|
||||
private final Locale[] languagesExcluded =
|
||||
{Locale.forLanguageTag("zh"), // TODO: Chinese symbols not yet available
|
||||
Locale.forLanguageTag("hi"), // TODO: Hindi (Indian) symbols not yet available
|
||||
Locale.forLanguageTag("ar"), // TODO: Arabic symbols not yet available, no translated entries yet
|
||||
Locale.forLanguageTag("ko"), // TODO: Korean symbols not yet available
|
||||
Locale.forLanguageTag("fa")}; // TODO: Farsi (Persian) symbols not yet available
|
||||
|
||||
private UIText nametext;
|
||||
private UISlider slider;
|
||||
private UILabel storageServiceStatus;
|
||||
private UIButton storageServiceAction;
|
||||
private UISlider heightSlider;
|
||||
private UISlider eyeHeightSlider;
|
||||
private UIImage img;
|
||||
private UICheckbox discordPresence;
|
||||
private UIDropdownScrollable<Locale> language;
|
||||
|
||||
private StorageServiceWorkerStatus storageServiceWorkerStatus;
|
||||
|
||||
@Override
|
||||
public void onOpened() {
|
||||
super.onOpened();
|
||||
if (nametext != null) {
|
||||
nametext.setText(config.getPlayer().getName());
|
||||
}
|
||||
if (slider != null) {
|
||||
Color color = config.getPlayer().getColor();
|
||||
slider.bindValue(new NotifyingBinding(findClosestIndex(color)));
|
||||
}
|
||||
if (heightSlider != null) {
|
||||
heightSlider.bindValue(new NotifyingBinding(config.getPlayer().getHeight()));
|
||||
}
|
||||
if (eyeHeightSlider != null) {
|
||||
eyeHeightSlider.bindValue(new NotifyingBinding(config.getPlayer().getEyeHeight()));
|
||||
}
|
||||
if (discordPresence != null) {
|
||||
discordPresence.setChecked(config.getPlayer().isDiscordPresence());
|
||||
}
|
||||
if (language != null) {
|
||||
language.setSelection(systemConfig.locale.get());
|
||||
}
|
||||
updateImage();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void initialise() {
|
||||
setAnimationSystem(MenuAnimationSystems.createDefaultSwipeAnimation());
|
||||
|
@ -117,62 +55,6 @@ public class PlayerSettingsScreen extends CoreScreenLayer {
|
|||
storageServiceAction = find("storageServiceAction", UIButton.class);
|
||||
updateStorageServiceStatus();
|
||||
|
||||
nametext = find("playername", UIText.class);
|
||||
if (nametext != null) {
|
||||
nametext.setTooltipDelay(0);
|
||||
nametext.bindTooltipString(new ReadOnlyBinding<String>() {
|
||||
@Override
|
||||
public String get() {
|
||||
return validateScreen();
|
||||
}
|
||||
});
|
||||
}
|
||||
img = find("image", UIImage.class);
|
||||
if (img != null) {
|
||||
ResourceUrn uri = TextureUtil.getTextureUriForColor(Color.WHITE);
|
||||
Texture tex = Assets.get(uri, Texture.class).get();
|
||||
img.setImage(tex);
|
||||
}
|
||||
|
||||
slider = find("tone", UISlider.class);
|
||||
if (slider != null) {
|
||||
slider.setIncrement(0.01f);
|
||||
Function<Object, String> constant = Functions.constant(" "); // ensure a certain width
|
||||
slider.setLabelFunction(constant);
|
||||
}
|
||||
|
||||
heightSlider = find("height", UISlider.class);
|
||||
if (heightSlider != null) {
|
||||
heightSlider.setMinimum(1.5f);
|
||||
heightSlider.setIncrement(0.1f);
|
||||
heightSlider.setRange(0.5f);
|
||||
heightSlider.setPrecision(1);
|
||||
}
|
||||
|
||||
eyeHeightSlider = find("eye-height", UISlider.class);
|
||||
if (eyeHeightSlider != null) {
|
||||
eyeHeightSlider.setMinimum(0.5f);
|
||||
eyeHeightSlider.setIncrement(0.1f);
|
||||
eyeHeightSlider.setRange(1f);
|
||||
eyeHeightSlider.setPrecision(1);
|
||||
}
|
||||
|
||||
discordPresence = find("discord-presence", UICheckbox.class);
|
||||
|
||||
language = find("language", UIDropdownScrollable.class);
|
||||
if (language != null) {
|
||||
SimpleUri menuUri = new SimpleUri("engine:menu");
|
||||
TranslationProject menuProject = translationSystem.getProject(menuUri);
|
||||
List<Locale> locales = new ArrayList<>(menuProject.getAvailableLocales());
|
||||
for (Locale languageExcluded : languagesExcluded) {
|
||||
locales.remove(languageExcluded);
|
||||
}
|
||||
Collections.sort(locales, ((Object o1, Object o2) -> (o1.toString().compareTo(o2.toString()))));
|
||||
language.setOptions(Lists.newArrayList(locales));
|
||||
language.setVisibleOptions(5); // Set maximum number of options visible for scrolling
|
||||
language.setOptionRenderer(new LocaleRenderer(translationSystem));
|
||||
}
|
||||
|
||||
WidgetUtil.trySubscribe(this, "close", button -> triggerBackAnimation());
|
||||
|
||||
IdentityIOHelper identityIOHelper = new IdentityIOHelper(context);
|
||||
|
@ -192,26 +74,6 @@ public class PlayerSettingsScreen extends CoreScreenLayer {
|
|||
}
|
||||
});
|
||||
|
||||
UIButton okButton = find("ok", UIButton.class);
|
||||
if (okButton != null) {
|
||||
okButton.subscribe(button -> {
|
||||
savePlayerSettings();
|
||||
triggerBackAnimation();
|
||||
});
|
||||
okButton.bindEnabled(new ReadOnlyBinding<Boolean>() {
|
||||
@Override
|
||||
public Boolean get() {
|
||||
return Strings.isNullOrEmpty(validateScreen());
|
||||
}
|
||||
});
|
||||
okButton.setTooltipDelay(0);
|
||||
okButton.bindTooltipString(new ReadOnlyBinding<String>() {
|
||||
@Override
|
||||
public String get() {
|
||||
return validateScreen();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -230,117 +92,8 @@ public class PlayerSettingsScreen extends CoreScreenLayer {
|
|||
storageServiceWorkerStatus = stat;
|
||||
}
|
||||
|
||||
private String validateScreen() {
|
||||
if (nametext != null) {
|
||||
if (Strings.isNullOrEmpty(nametext.getText()) || nametext.getText().trim().length() == 0) {
|
||||
return translationSystem.translate("${engine:menu#missing-name-message}");
|
||||
}
|
||||
if (nametext.getText().trim().length() > 100) {
|
||||
return translationSystem.translate("${engine:menu#validation-username-max-length}");
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private float findClosestIndex(Color color) {
|
||||
int best = 0;
|
||||
float minDist = Float.MAX_VALUE;
|
||||
for (int i = 0; i < colors.size(); i++) {
|
||||
Color other = colors.get(i);
|
||||
float dr = other.rf() - color.rf();
|
||||
float dg = other.gf() - color.gf();
|
||||
float db = other.bf() - color.bf();
|
||||
|
||||
// there are certainly smarter ways to measure color distance,
|
||||
// but Euclidean distance is good enough for the purpose
|
||||
float dist = dr * dr + dg * dg + db * db;
|
||||
if (dist < minDist) {
|
||||
minDist = dist;
|
||||
best = i;
|
||||
}
|
||||
}
|
||||
|
||||
float max = colors.size() - 1;
|
||||
return best / max;
|
||||
}
|
||||
|
||||
private Color findClosestColor(float findex) {
|
||||
int index = DoubleMath.roundToInt(findex * (double) (colors.size() - 1), RoundingMode.HALF_UP);
|
||||
Color color = colors.get(index);
|
||||
return color;
|
||||
}
|
||||
|
||||
private void updateImage() {
|
||||
Color color = getColor();
|
||||
if (img != null) {
|
||||
img.setTint(color);
|
||||
}
|
||||
}
|
||||
|
||||
private Color getColor() {
|
||||
if (slider != null) {
|
||||
float index = slider.getValue();
|
||||
return findClosestColor(index);
|
||||
} else {
|
||||
return config.getPlayer().getColor();
|
||||
}
|
||||
}
|
||||
|
||||
private Float getHeight() {
|
||||
if (heightSlider != null) {
|
||||
float index = heightSlider.getValue();
|
||||
return index;
|
||||
} else {
|
||||
return config.getPlayer().getHeight();
|
||||
}
|
||||
}
|
||||
|
||||
private Float getEyeHeight() {
|
||||
if (eyeHeightSlider != null) {
|
||||
float index = eyeHeightSlider.getValue();
|
||||
return index;
|
||||
} else {
|
||||
return config.getPlayer().getEyeHeight();
|
||||
}
|
||||
}
|
||||
|
||||
private void savePlayerSettings() {
|
||||
Color color = getColor();
|
||||
config.getPlayer().setColor(color);
|
||||
Float height = getHeight();
|
||||
config.getPlayer().setHeight(height);
|
||||
Float eyeHeight = getEyeHeight();
|
||||
config.getPlayer().setEyeHeight(eyeHeight);
|
||||
config.getPlayer().setDiscordPresence(discordPresence.isChecked());
|
||||
if (nametext != null) {
|
||||
config.getPlayer().setName(nametext.getText().trim());
|
||||
config.getPlayer().setHasEnteredUsername(true);
|
||||
}
|
||||
if (!systemConfig.locale.get().equals(language.getSelection())) {
|
||||
systemConfig.locale.set(language.getSelection());
|
||||
getManager().invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLowerLayerVisible() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls update() in parent class when the slider value changes
|
||||
*/
|
||||
private final class NotifyingBinding extends DefaultBinding<Float> {
|
||||
|
||||
private NotifyingBinding(Float value) {
|
||||
super(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(Float v) {
|
||||
super.set(v);
|
||||
|
||||
updateImage();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import org.joml.Vector3ic;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.terasology.engine.config.Config;
|
||||
import org.terasology.engine.config.PlayerConfig;
|
||||
import org.terasology.engine.config.RenderingConfig;
|
||||
import org.terasology.engine.context.Context;
|
||||
import org.terasology.engine.core.GameEngine;
|
||||
|
@ -139,7 +140,7 @@ public final class WorldRendererImpl implements WorldRenderer {
|
|||
* in match.
|
||||
*/
|
||||
vrProvider.getState().setGroundPlaneYOffset(
|
||||
GROUND_PLANE_HEIGHT_DISPARITY - context.get(Config.class).getPlayer().getEyeHeight());
|
||||
GROUND_PLANE_HEIGHT_DISPARITY - context.get(PlayerConfig.class).eyeHeight.get());
|
||||
currentRenderingStage = RenderingStage.LEFT_EYE;
|
||||
} else {
|
||||
playerCamera = new PerspectiveCamera(worldProvider, renderingConfig, context.get(DisplayDevice.class));
|
||||
|
|
|
@ -1,18 +1,5 @@
|
|||
/*
|
||||
* Copyright 2017 MovingBlocks
|
||||
*
|
||||
* Licensed 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.
|
||||
*/
|
||||
// Copyright 2021 The Terasology Foundation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
package org.terasology.engine.telemetry.metrics;
|
||||
|
||||
import com.snowplowanalytics.snowplow.tracker.events.Unstructured;
|
||||
|
@ -97,8 +84,8 @@ public final class GameConfigurationMetric extends Metric {
|
|||
SystemConfig systemConfig = context.get(SystemConfig.class);
|
||||
language = systemConfig.locale.get().toString();
|
||||
|
||||
PlayerConfig playerConfig = config.getPlayer();
|
||||
playerHeight = playerConfig.getHeight();
|
||||
playerEyeHeight = playerConfig.getEyeHeight();
|
||||
PlayerConfig playerConfig = context.get(PlayerConfig.class);
|
||||
playerHeight = playerConfig.height.get();
|
||||
playerEyeHeight = playerConfig.eyeHeight.get();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"type": "ColumnLayout",
|
||||
"horizontalSpacing": 10,
|
||||
"contents": [
|
||||
{
|
||||
"type": "UISlider",
|
||||
"id": "tone"
|
||||
},
|
||||
{
|
||||
"type": "UIImage",
|
||||
"skin": "framed_image",
|
||||
"id": "image"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -113,6 +113,7 @@
|
|||
"dialog-yes": "dialog-yes",
|
||||
"disable-all-modules": "disable-all-modules",
|
||||
"discord-presence": "discord-presence",
|
||||
"discord-settings-title": "discord-settings-title",
|
||||
"drop-item": "drop-item",
|
||||
"download-module": "download-module",
|
||||
"downloading-server-list": "downloading-server-list",
|
||||
|
|
|
@ -117,6 +117,7 @@
|
|||
"disable-launch-popup": "Remember and don't show again",
|
||||
"disable-rendering-class": "Disable",
|
||||
"discord-presence": "Discord Rich Presence",
|
||||
"discord-settings-title": "Discord Settings",
|
||||
"download-module": "Download",
|
||||
"downloading-server-list": "Downloading server list ..",
|
||||
"drop-item": "Drop Item",
|
||||
|
|
|
@ -5,26 +5,42 @@
|
|||
"type": "RelativeLayout",
|
||||
"contents": [
|
||||
{
|
||||
"type": "ColumnLayout",
|
||||
"id": "mainContainer",
|
||||
"fillVerticalSpace": false,
|
||||
"layoutInfo": {
|
||||
"use-content-height": true,
|
||||
"position-horizontal-center": {}
|
||||
"type": "ScrollableArea",
|
||||
"content": {
|
||||
"type": "ColumnLayout",
|
||||
"id": "mainContainer",
|
||||
"fillVerticalSpace": false,
|
||||
"layoutInfo": {
|
||||
"use-content-height": true,
|
||||
"position-horizontal-center": {}
|
||||
},
|
||||
"contents": []
|
||||
},
|
||||
"contents": []
|
||||
"layoutInfo": {
|
||||
"width": 800,
|
||||
"position-horizontal-center": {},
|
||||
"position-top": {
|
||||
"target": "TOP",
|
||||
"offset": 48
|
||||
},
|
||||
"position-bottom": {
|
||||
"target": "TOP",
|
||||
"offset": 32,
|
||||
"widget": "close"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "UIButton",
|
||||
"text": "${engine:menu#back}",
|
||||
"id": "close",
|
||||
"layoutInfo": {
|
||||
"height": 32,
|
||||
"width": 200,
|
||||
"position-horizontal-center": {},
|
||||
"position-bottom": {
|
||||
"target": "BOTTOM",
|
||||
"offset": 48
|
||||
"height": 32,
|
||||
"width": 200,
|
||||
"position-horizontal-center": {},
|
||||
"position-bottom": {
|
||||
"target": "BOTTOM",
|
||||
"offset": 48
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,36 +32,6 @@
|
|||
"horizontalSpacing": 8,
|
||||
"overrideChildEnabledProp" : false,
|
||||
"contents": [
|
||||
{
|
||||
"type": "UILabel",
|
||||
"text": "${engine:menu#player-name}:"
|
||||
},
|
||||
{
|
||||
"type": "UIText",
|
||||
"id": "playername"
|
||||
},
|
||||
{
|
||||
"type": "UILabel",
|
||||
"text": "${engine:menu#player-color}:"
|
||||
},
|
||||
{
|
||||
"type": "RowLayout",
|
||||
"horizontalSpacing": 10,
|
||||
"contents": [
|
||||
{
|
||||
"type": "UISlider",
|
||||
"id": "tone",
|
||||
"layoutInfo": {
|
||||
"relativeWidth": 0.88
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "UIImage",
|
||||
"skin": "framed_image",
|
||||
"id": "image"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "UILabel",
|
||||
"text": "Multiplayer identities:",
|
||||
|
@ -108,64 +78,6 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "UILabel",
|
||||
"text": "${engine:menu#settings-language}:"
|
||||
},
|
||||
{
|
||||
"type": "UIDropdownScrollable",
|
||||
"id": "language"
|
||||
},
|
||||
{
|
||||
"type": "UILabel",
|
||||
"text": "${engine:menu#experimental}"
|
||||
},
|
||||
{
|
||||
"type": "UILabel",
|
||||
"text": ""
|
||||
},
|
||||
{
|
||||
"type": "UILabel",
|
||||
"text": "${engine:menu#player-height}:"
|
||||
},
|
||||
{
|
||||
"type": "RowLayout",
|
||||
"horizontalSpacing": 10,
|
||||
"contents": [
|
||||
{
|
||||
"type": "UISlider",
|
||||
"id": "height"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "UILabel",
|
||||
"text": "${engine:menu#player-eye-height}:"
|
||||
},
|
||||
{
|
||||
"type": "RowLayout",
|
||||
"horizontalSpacing": 10,
|
||||
"contents": [
|
||||
{
|
||||
"type": "UISlider",
|
||||
"id": "eye-height"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "UILabel",
|
||||
"text": "${engine:menu#discord-presence}:"
|
||||
},
|
||||
{
|
||||
"type": "RowLayout",
|
||||
"horizontalSpacing": 10,
|
||||
"contents": [
|
||||
{
|
||||
"type": "UICheckbox",
|
||||
"id": "discord-presence"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"layoutInfo": {
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
// Copyright 2021 The Terasology Foundation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package org.terasology.subsystem.discordrpc;
|
||||
|
||||
import org.terasology.engine.config.flexible.AutoConfig;
|
||||
import org.terasology.engine.config.flexible.Setting;
|
||||
|
||||
import static org.terasology.engine.config.flexible.SettingArgument.defaultValue;
|
||||
import static org.terasology.engine.config.flexible.SettingArgument.name;
|
||||
import static org.terasology.engine.config.flexible.SettingArgument.type;
|
||||
|
||||
public class DiscordAutoConfig extends AutoConfig {
|
||||
|
||||
public final Setting<Boolean> discordPresence =
|
||||
setting(
|
||||
type(Boolean.class),
|
||||
defaultValue(true),
|
||||
name("${engine:menu#discord-presence}")
|
||||
);
|
||||
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "${engine:menu#discord-settings-title}";
|
||||
}
|
||||
}
|
|
@ -1,45 +1,28 @@
|
|||
/*
|
||||
* Copyright 2018 MovingBlocks
|
||||
*
|
||||
* Licensed 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.
|
||||
*/
|
||||
// Copyright 2021 The Terasology Foundation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
package org.terasology.subsystem.discordrpc;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.terasology.engine.config.Config;
|
||||
import org.terasology.engine.config.PlayerConfig;
|
||||
import org.terasology.engine.context.Context;
|
||||
import org.terasology.engine.core.GameEngine;
|
||||
import org.terasology.engine.core.subsystem.EngineSubsystem;
|
||||
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.time.OffsetDateTime;
|
||||
|
||||
/**
|
||||
* Subsystem that manages Discord RPC in the game client, such as status or connection.
|
||||
* This subsystem can be enhanced further to improve game presentation in rich presence.
|
||||
*
|
||||
* Subsystem that manages Discord RPC in the game client, such as status or connection. This subsystem can be enhanced
|
||||
* further to improve game presentation in rich presence.
|
||||
* <p>
|
||||
* It communicates with the thread safely using thread-safe shared buffer.
|
||||
*
|
||||
* @see EngineSubsystem
|
||||
*/
|
||||
public final class DiscordRPCSubSystem implements EngineSubsystem, PropertyChangeListener {
|
||||
public final class DiscordRPCSubSystem implements EngineSubsystem {
|
||||
private static final Logger logger = LoggerFactory.getLogger(DiscordRPCSubSystem.class);
|
||||
private static DiscordRPCSubSystem instance;
|
||||
|
||||
private Config config;
|
||||
private DiscordAutoConfig config;
|
||||
private DiscordRPCThread thread;
|
||||
|
||||
public DiscordRPCSubSystem() throws IllegalStateException {
|
||||
|
@ -50,58 +33,10 @@ public final class DiscordRPCSubSystem implements EngineSubsystem, PropertyChang
|
|||
instance = this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialise(GameEngine engine, Context rootContext) {
|
||||
logger.info("Initializing...");
|
||||
|
||||
thread = new DiscordRPCThread();
|
||||
thread.getBuffer().setState("In Main Menu");
|
||||
|
||||
config = rootContext.get(Config.class);
|
||||
|
||||
if (config.getPlayer().isDiscordPresence()) {
|
||||
thread.enable();
|
||||
} else {
|
||||
logger.info("Discord RPC is disabled! No connection is being made during initialization.");
|
||||
thread.disable();
|
||||
}
|
||||
thread.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void postInitialise(Context context) {
|
||||
config = context.get(Config.class);
|
||||
config.getPlayer().subscribe(this);
|
||||
|
||||
if (config.getPlayer().isDiscordPresence()) {
|
||||
thread.enable();
|
||||
} else {
|
||||
thread.disable();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void propertyChange(PropertyChangeEvent evt) {
|
||||
if (evt.getPropertyName().equals(PlayerConfig.DISCORD_PRESENCE)) {
|
||||
thread.setEnabled((boolean) evt.getNewValue());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void preShutdown() {
|
||||
thread.disable();
|
||||
thread.stop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "DiscordRPC";
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-discovers the discord ipc in case the player started the discord client after running the game.
|
||||
* And, the re-connecting process failed to connect.
|
||||
*
|
||||
* Re-discovers the discord ipc in case the player started the discord client after running the game. And, the
|
||||
* re-connecting process failed to connect.
|
||||
* <p>
|
||||
* This should be called once by {@link DiscordRPCSystem}
|
||||
*/
|
||||
public static void discover() {
|
||||
|
@ -117,6 +52,7 @@ public final class DiscordRPCSubSystem implements EngineSubsystem, PropertyChang
|
|||
|
||||
/**
|
||||
* Sets the name of the gameplay the player is playing (e.g. Custom, Josharias Survival, etc...)
|
||||
*
|
||||
* @param name the name of the gameplay
|
||||
*/
|
||||
public static void setGameplayName(String name) {
|
||||
|
@ -163,4 +99,45 @@ public final class DiscordRPCSubSystem implements EngineSubsystem, PropertyChang
|
|||
private static DiscordRPCSubSystem getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialise(GameEngine engine, Context rootContext) {
|
||||
logger.info("Initializing...");
|
||||
|
||||
thread = new DiscordRPCThread();
|
||||
thread.getBuffer().setState("In Main Menu");
|
||||
|
||||
config = rootContext.get(DiscordAutoConfig.class);
|
||||
|
||||
if (config.discordPresence.get()) {
|
||||
thread.enable();
|
||||
} else {
|
||||
logger.info("Discord RPC is disabled! No connection is being made during initialization.");
|
||||
thread.disable();
|
||||
}
|
||||
thread.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void postInitialise(Context context) {
|
||||
config = context.get(DiscordAutoConfig.class);
|
||||
config.discordPresence.subscribe((setting, old) -> {
|
||||
if (setting.get()) {
|
||||
thread.enable();
|
||||
} else {
|
||||
thread.disable();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void preShutdown() {
|
||||
thread.disable();
|
||||
thread.stop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "DiscordRPC";
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue