Skip to content

Commit f97a2f7

Browse files
authored
Add support for tip conditions and other features. (#143)
* Update build dependencies. * Add a config option to hide tips that have not been localized to your current language. * Improve performance when checking if a tip can be displayed on the current screen. * Add support for tip conditions. * Add a config option to control the width of tips. * Add a config option to define the default tip title. * Temporarily disable Jenkins.
1 parent d718c85 commit f97a2f7

File tree

13 files changed

+721
-106
lines changed

13 files changed

+721
-106
lines changed

Jenkinsfile

Lines changed: 0 additions & 39 deletions
This file was deleted.

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ buildscript {
1212
}
1313

1414
plugins {
15-
id 'fabric-loom' version '1.2-SNAPSHOT' apply(false)
15+
id 'fabric-loom' version '1.6-SNAPSHOT' apply(false)
1616
id 'net.minecraftforge.gradle' version '[6.0,6.2)' apply(false)
1717
id 'org.spongepowered.gradle.vanilla' version '0.2.1-SNAPSHOT' apply(false)
1818
id 'org.spongepowered.mixin' version '0.7-SNAPSHOT' apply(false)

common/src/main/java/net/darkhax/tipsmod/api/TipsAPI.java

Lines changed: 20 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,15 @@
66
import net.darkhax.tipsmod.impl.TipsModCommon;
77
import net.darkhax.tipsmod.impl.resources.SimpleTip;
88
import net.minecraft.ChatFormatting;
9+
import net.minecraft.client.Minecraft;
910
import net.minecraft.client.gui.screens.Screen;
11+
import net.minecraft.client.gui.screens.achievement.StatsScreen;
1012
import net.minecraft.client.resources.language.I18n;
1113
import net.minecraft.network.chat.Component;
12-
import net.minecraft.network.chat.ComponentContents;
1314
import net.minecraft.network.chat.contents.TranslatableContents;
1415
import net.minecraft.resources.ResourceLocation;
1516

17+
import javax.annotation.Nullable;
1618
import java.util.HashMap;
1719
import java.util.HashSet;
1820
import java.util.List;
@@ -24,11 +26,13 @@ public class TipsAPI {
2426

2527
public static final ResourceLocation DEFAULT_SERIALIZER = new ResourceLocation("tips", "simple_tip");
2628
public static final Component DEFAULT_TITLE = Component.translatable("tipsmod.title.default").withStyle(ChatFormatting.BOLD, ChatFormatting.UNDERLINE, ChatFormatting.YELLOW);
27-
public static final ITip EMPTY = new SimpleTip(new ResourceLocation(Constants.MOD_ID, "empty"), DEFAULT_TITLE, Component.literal("No tips loaded. Please review your config options!"), Optional.of(999999));
28-
private static Map<ResourceLocation, ITipSerializer<?>> SERIALIZERS = new HashMap<>();
29-
private static Set<Class<? extends Screen>> SCREENS = new HashSet<>();
29+
private static final Map<ResourceLocation, ITipSerializer<?>> SERIALIZERS = new HashMap<>();
30+
private static final Set<Class<? extends Screen>> SCREENS = new HashSet<>();
3031
private static int currentTipIndex = 0;
3132

33+
@Deprecated
34+
public static final ITip EMPTY = new SimpleTip(new ResourceLocation(Constants.MOD_ID, "empty"), DEFAULT_TITLE, Component.literal("This is deprecated and should no longer be used."), Optional.of(0));
35+
3236
public static void registerTipSerializer(ResourceLocation id, ITipSerializer<?> serializer) {
3337

3438
SERIALIZERS.put(id, serializer);
@@ -41,12 +45,19 @@ public static void registerTipScreen(Class<? extends Screen> screenClass) {
4145

4246
public static boolean canRenderOnScreen(Screen screen) {
4347

44-
return SCREENS.stream().filter(clazz -> clazz.isInstance(screen)).count() > 0;
48+
return SCREENS.stream().anyMatch(clazz -> clazz.isInstance(screen));
4549
}
4650

51+
@Nullable
52+
@Deprecated
4753
public static ITip getRandomTip() {
54+
return getRandomTip(Minecraft.getInstance().screen);
55+
}
4856

49-
final List<ITip> filteredTips = getLoadedTips().stream().filter(TipsAPI::canDisplayTip).toList();
57+
@Nullable
58+
public static ITip getRandomTip(Screen screen) {
59+
60+
final List<ITip> filteredTips = getLoadedTips().stream().filter(tip -> TipsAPI.canDisplayTip(tip) && tip.canDisplayOnScreen(screen)).toList();
5061

5162
if (currentTipIndex + 1 > filteredTips.size()) {
5263

@@ -58,7 +69,7 @@ public static ITip getRandomTip() {
5869
return filteredTips.get(currentTipIndex++);
5970
}
6071

61-
return EMPTY;
72+
return null;
6273
}
6374

6475
public static ITipSerializer<?> getTipSerializer(ResourceLocation id) {
@@ -74,51 +85,36 @@ public static List<ITip> getLoadedTips() {
7485
public static boolean canDisplayTip(ITip tip) {
7586

7687
if (tip == null) {
77-
7888
return false;
7989
}
8090

8191
if (tip.getId() == null) {
82-
8392
Constants.LOG.error("Found invalid tip without an ID. Object: {}, Class: {}", tip, tip.getClass());
8493
return false;
8594
}
8695

8796
else if (tip.getTitle() == null) {
88-
8997
Constants.LOG.error("Found invalid tip. Title is null. Object: {}, Class: {}, ID: {}", tip, tip.getClass(), tip.getId());
9098
return false;
9199
}
92100

93101
else if (tip.getText() == null) {
94-
95102
Constants.LOG.error("Found invalid tip. Text is null. Object: {}, Class: {}, ID: {}", tip, tip.getClass(), tip.getId());
96103
return false;
97104
}
98105

99106
final ResourceLocation id = tip.getId();
100107

101108
if (TipsModCommon.CONFIG.ignoredNamespaces.contains(id.getNamespace())) {
102-
103109
return false;
104110
}
105111

106112
if (TipsModCommon.CONFIG.ignoredTips.contains(id.toString())) {
107-
108113
return false;
109114
}
110115

111-
final ComponentContents contents = tip.getText().getContents();
112-
113-
if (contents instanceof TranslatableContents) {
114-
115-
final String key = ((TranslatableContents) contents).getKey();
116-
117-
// Ignore tips that don't have a localization in the current language.
118-
if (!I18n.exists(key)) {
119-
120-
return false;
121-
}
116+
if (TipsModCommon.CONFIG.hideUnlocalizedTips && tip.getText().getContents() instanceof TranslatableContents translatable && !I18n.exists(translatable.getKey())) {
117+
return false;
122118
}
123119

124120
return true;
Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,56 @@
11
package net.darkhax.tipsmod.api.resources;
22

3+
import net.darkhax.tipsmod.api.TipsAPI;
34
import net.darkhax.tipsmod.impl.TipsModCommon;
5+
import net.minecraft.client.gui.screens.Screen;
46
import net.minecraft.network.chat.Component;
57
import net.minecraft.resources.ResourceLocation;
68

79
/**
810
* Defines a tip that is displayed on certain menus.
911
*/
1012
public interface ITip {
11-
13+
1214
/**
1315
* Gets the namespaced identifier for the tip.
14-
*
16+
*
1517
* @return The namespaced identifier for the tip.
1618
*/
17-
ResourceLocation getId ();
18-
19+
ResourceLocation getId();
20+
1921
/**
20-
* Gets the title for the tip. This is the part on top of the tip which explains what it
21-
* is.
22-
*
22+
* Gets the title for the tip. This is the part on top of the tip which explains what it is.
23+
*
2324
* @return The title of the tip.
2425
*/
25-
Component getTitle ();
26-
26+
Component getTitle();
27+
2728
/**
2829
* Gets the body of the tip. This is the part below the title.
29-
*
30+
*
3031
* @return The body of the tip.
3132
*/
32-
Component getText ();
33-
33+
Component getText();
34+
3435
/**
35-
* Gets the amount of time until the next tip can be displayed. By default this will be the
36-
* config defined cycle time.
37-
*
36+
* Gets the amount of time until the next tip can be displayed. By default, this will be the config defined cycle
37+
* time.
38+
*
3839
* @return The amount of time in ticks until the next tip will be displayed.
3940
*/
40-
default int getCycleTime () {
41+
default int getCycleTime() {
4142

4243
return TipsModCommon.CONFIG.defaultCycleTime;
4344
}
45+
46+
/**
47+
* Tests if the tip can be displayed on the specified screen.
48+
*
49+
* @param screen The screen to test.
50+
* @return If the tip can be displayed on the screen.
51+
*/
52+
default boolean canDisplayOnScreen(Screen screen) {
53+
54+
return TipsAPI.canRenderOnScreen(screen);
55+
}
4456
}

common/src/main/java/net/darkhax/tipsmod/impl/Config.java

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,28 @@
22

33
import com.google.gson.Gson;
44
import com.google.gson.GsonBuilder;
5+
import com.google.gson.JsonDeserializationContext;
6+
import com.google.gson.JsonDeserializer;
7+
import com.google.gson.JsonElement;
8+
import com.google.gson.JsonParseException;
9+
import com.google.gson.JsonSerializationContext;
10+
import com.google.gson.JsonSerializer;
511
import com.google.gson.annotations.Expose;
612
import net.darkhax.bookshelf.api.Services;
13+
import net.darkhax.bookshelf.api.serialization.Serializers;
14+
import net.darkhax.tipsmod.api.TipsAPI;
15+
import net.minecraft.network.chat.Component;
716

817
import java.io.File;
918
import java.io.FileReader;
1019
import java.io.FileWriter;
20+
import java.lang.reflect.Type;
1121
import java.util.ArrayList;
1222
import java.util.List;
1323

1424
public class Config {
1525

16-
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().excludeFieldsWithoutExposeAnnotation().create();
26+
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().registerTypeAdapter(Component.class, new ComponentTypeAdapter()).excludeFieldsWithoutExposeAnnotation().create();
1727

1828
@Expose
1929
public int defaultCycleTime = 5000;
@@ -24,6 +34,15 @@ public class Config {
2434
@Expose
2535
public List<String> ignoredTips = new ArrayList<>();
2636

37+
@Expose
38+
public boolean hideUnlocalizedTips = false;
39+
40+
@Expose
41+
public float tipRenderWidthPercent = 0.35f;
42+
43+
@Expose
44+
public Component defaultTitle = TipsAPI.DEFAULT_TITLE;
45+
2746
public static Config load() {
2847

2948
File configFile = Services.PLATFORM.getConfigPath().resolve("tips.json").toFile();
@@ -64,4 +83,17 @@ public static Config load() {
6483

6584
return config;
6685
}
86+
87+
private static final class ComponentTypeAdapter implements JsonSerializer<Component>, JsonDeserializer<Component> {
88+
89+
@Override
90+
public Component deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
91+
return Serializers.TEXT.fromJSON(json);
92+
}
93+
94+
@Override
95+
public JsonElement serialize(Component src, Type typeOfSrc, JsonSerializationContext context) {
96+
return Serializers.TEXT.toJSON(src);
97+
}
98+
}
6799
}

common/src/main/java/net/darkhax/tipsmod/impl/client/TipRenderHandler.java

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,47 +3,55 @@
33
import net.darkhax.bookshelf.api.util.RenderHelper;
44
import net.darkhax.tipsmod.api.TipsAPI;
55
import net.darkhax.tipsmod.api.resources.ITip;
6-
import net.darkhax.tipsmod.impl.Constants;
6+
import net.darkhax.tipsmod.impl.TipsModCommon;
77
import net.minecraft.client.gui.GuiGraphics;
88
import net.minecraft.client.gui.screens.Screen;
99
import net.minecraft.util.Mth;
1010

11+
import javax.annotation.Nullable;
12+
import java.lang.ref.WeakReference;
13+
1114
public class TipRenderHandler {
1215

1316
private static long initTime = System.currentTimeMillis();
17+
18+
@Nullable
1419
private static ITip tip;
1520

21+
@Nullable
22+
private static WeakReference<Screen> lastScreen;
23+
1624
private static void setTip(ITip newTip) {
1725

26+
// The empty tip is deprecated and is now replaced with null.
27+
if (newTip == TipsAPI.EMPTY) {
28+
newTip = null;
29+
}
30+
1831
tip = newTip;
1932
initTime = System.currentTimeMillis();
2033
}
2134

2235
public static void drawTip(GuiGraphics graphics, Screen parentScreen) {
2336

24-
if (tip == null) {
25-
26-
setTip(TipsAPI.getRandomTip());
37+
// If the tip is null, and we're on a new screen try to load a new tip.
38+
if (tip == null && (lastScreen == null || !lastScreen.refersTo(parentScreen))) {
39+
setTip(TipsAPI.getRandomTip(parentScreen));
40+
lastScreen = new WeakReference<>(parentScreen);
2741
}
2842

29-
if (TipsAPI.canRenderOnScreen(parentScreen)) {
43+
if (tip != null) {
3044

45+
// Cycle to the next tip if the timer has expired.
3146
final long currentTime = System.currentTimeMillis();
3247
final int currentCycleTime = tip.getCycleTime();
33-
3448
if (currentTime - initTime > currentCycleTime) {
35-
36-
setTip(TipsAPI.getRandomTip());
37-
38-
if (tip != null) {
39-
40-
Constants.LOG.debug("Displaying tip {} on screen {}.", tip.getId(), parentScreen.getClass().getSimpleName());
41-
}
49+
setTip(TipsAPI.getRandomTip(parentScreen));
4250
}
4351

44-
if (tip != null) {
45-
46-
final int textWidth = Mth.floor(parentScreen.width * 0.35f);
52+
// Render the tip.
53+
if (tip != null && tip.canDisplayOnScreen(parentScreen)) {
54+
final int textWidth = Mth.floor(parentScreen.width * TipsModCommon.CONFIG.tipRenderWidthPercent);
4755
int height = parentScreen.height - 10;
4856
height -= RenderHelper.renderLinesReversed(graphics, 10, height, tip.getText(), textWidth);
4957
height -= 3; // padding for title

0 commit comments

Comments
 (0)