Skip to content

Commit 18e4562

Browse files
committed
v1.2.0: Add click-to-remove messages, world event handling, and update to MC 1.21.10
1 parent 17c11ee commit 18e4562

17 files changed

+398
-4
lines changed

CHANGELOG.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,31 @@
11
# Changelog
22

3+
## [1.2.0] - 2024-11-12
4+
5+
### Added
6+
7+
- Click-to-remove message functionality with particle effects
8+
- Configuration option to enable/disable click-to-remove feature
9+
- World event handling system for message parsing pause/resume
10+
- Automatic message parsing pause when leaving worlds
11+
- Automatic message parsing resume when joining worlds
12+
13+
### Changed
14+
15+
- Updated Minecraft version from 1.21.7 to 1.21.10
16+
- Updated Fabric API to 0.129.0+1.21.7
17+
- Fixed WorldRenderEvents imports (moved to v1.world package)
18+
- Updated rendering API calls (matrixStack() → matrices())
19+
- Fixed MinecraftClient.disconnect() mixin signature for new boolean parameter
20+
21+
### Technical
22+
23+
- MouseHandlerMixin for click detection on messages
24+
- MessageClickHandler for click processing and particle spawning
25+
- WorldEventHandler for managing message parsing state
26+
- ClientPlayNetworkHandlerMixin for world join detection
27+
- MinecraftClientMixin for world leave detection
28+
329
## [1.1.0] - 2024-11-11
430

531
### Added

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ loader_version=0.16.14
1010
loom_version=1.11-SNAPSHOT
1111

1212
# Mod Properties
13-
mod_version=1.1.0
13+
mod_version=1.2.0
1414
maven_group=takeyourminestream.modid
1515
archives_base_name=tyms
1616

src/client/java/takeyourminestream/modid/ConfigManager.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,9 @@ public void setConfigValue(String key, Object value) {
116116
case "followPlayer":
117117
configData.setFollowPlayer((Boolean) value);
118118
break;
119+
case "enableClickToRemove":
120+
configData.setEnableClickToRemove((Boolean) value);
121+
break;
119122
default:
120123
LOGGER.warning("Неизвестный ключ конфигурации: " + key);
121124
return;
@@ -143,6 +146,7 @@ private void updateConfigCache() {
143146
configCache.put("messageScale", configData.getMessageScale());
144147
configCache.put("showMessageBackground", configData.isShowMessageBackground());
145148
configCache.put("followPlayer", configData.isFollowPlayer());
149+
configCache.put("enableClickToRemove", configData.isEnableClickToRemove());
146150
}
147151

148152
public ModConfigData getConfigData() {

src/client/java/takeyourminestream/modid/ModConfig.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,4 +113,13 @@ public static boolean isFOLLOW_PLAYER() {
113113
public static void setFOLLOW_PLAYER(boolean value) {
114114
ConfigManager.getInstance().setConfigValue("followPlayer", value);
115115
}
116+
117+
public static boolean isENABLE_CLICK_TO_REMOVE() {
118+
Object value = ConfigManager.getInstance().getConfigValue("enableClickToRemove");
119+
return value != null ? (Boolean) value : true; // По умолчанию true
120+
}
121+
122+
public static void setENABLE_CLICK_TO_REMOVE(boolean value) {
123+
ConfigManager.getInstance().setConfigValue("enableClickToRemove", value);
124+
}
116125
}

src/client/java/takeyourminestream/modid/ModConfigScreen.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,16 @@ private void createConfigEntries() {
232232
this.addDrawableChild(followPlayerButton);
233233
configEntries.add(new ConfigEntry("takeyourminestream.config.follow_player", "takeyourminestream.config.follow_player.desc", ConfigEntryType.TOGGLE, followPlayerButton, ConfigCategory.BEHAVIOR));
234234

235+
ButtonWidget clickToRemoveButton = ButtonWidget.builder(
236+
Text.translatable(ModConfig.isENABLE_CLICK_TO_REMOVE() ? "takeyourminestream.config.on" : "takeyourminestream.config.off"),
237+
btn -> {
238+
ModConfig.setENABLE_CLICK_TO_REMOVE(!ModConfig.isENABLE_CLICK_TO_REMOVE());
239+
btn.setMessage(Text.translatable(ModConfig.isENABLE_CLICK_TO_REMOVE() ? "takeyourminestream.config.on" : "takeyourminestream.config.off"));
240+
}
241+
).dimensions(0, 0, CONTROL_WIDTH, 20).build();
242+
this.addDrawableChild(clickToRemoveButton);
243+
configEntries.add(new ConfigEntry("takeyourminestream.config.click_to_remove", "takeyourminestream.config.click_to_remove.desc", ConfigEntryType.TOGGLE, clickToRemoveButton, ConfigCategory.BEHAVIOR));
244+
235245
TextFieldWidget maxFreezeDistanceField = new TextFieldWidget(textRenderer, 0, 0, CONTROL_WIDTH, 20, Text.translatable("takeyourminestream.config.max_freeze_distance"));
236246
maxFreezeDistanceField.setText(String.valueOf(ModConfig.getMAX_FREEZE_DISTANCE()));
237247
maxFreezeDistanceField.setChangedListener(s -> {

src/client/java/takeyourminestream/modid/TakeYourMineStreamClient.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ private void initializeMod() {
5050
commandManager.registerCommands();
5151
keyBindingManager.registerKeyBindings();
5252

53+
// Регистрация обработчиков событий мира
54+
WorldEventHandler.register(messageSpawner);
55+
5356
Logger.info("Все компоненты мода инициализированы");
5457
}
5558

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package takeyourminestream.modid;
2+
3+
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents;
4+
import takeyourminestream.modid.messages.MessageSpawner;
5+
import takeyourminestream.modid.utils.Logger;
6+
7+
/**
8+
* Обработчик событий мира для управления паузой системы сообщений
9+
*/
10+
public class WorldEventHandler {
11+
12+
/**
13+
* Регистрирует обработчики событий входа/выхода из мира
14+
* @param messageSpawner система спавна сообщений
15+
*/
16+
public static void register(MessageSpawner messageSpawner) {
17+
// При выходе из мира - ставим на паузу
18+
ClientLifecycleEvents.CLIENT_STOPPING.register(client -> {
19+
if (messageSpawner != null) {
20+
messageSpawner.pause();
21+
Logger.info("Система сообщений поставлена на паузу (выход из игры)");
22+
}
23+
});
24+
}
25+
26+
/**
27+
* Обработчик входа в мир - снимает с паузы
28+
* Вызывается вручную при входе в мир
29+
* @param messageSpawner система спавна сообщений
30+
*/
31+
public static void onWorldJoin(MessageSpawner messageSpawner) {
32+
if (messageSpawner != null && messageSpawner.isPaused()) {
33+
messageSpawner.resume();
34+
Logger.info("Система сообщений снята с паузы (вход в мир)");
35+
}
36+
}
37+
38+
/**
39+
* Обработчик выхода из мира - ставит на паузу
40+
* Вызывается вручную при выходе из мира
41+
* @param messageSpawner система спавна сообщений
42+
*/
43+
public static void onWorldLeave(MessageSpawner messageSpawner) {
44+
if (messageSpawner != null && !messageSpawner.isPaused()) {
45+
messageSpawner.pause();
46+
Logger.info("Система сообщений поставлена на паузу (выход из мира)");
47+
}
48+
}
49+
}

src/client/java/takeyourminestream/modid/config/ModConfigData.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* Модель данных конфигурации мода
55
*/
66
public class ModConfigData {
7-
private String twitchChannelName = "ijustseen_you";
7+
private String twitchChannelName = "ijustseen";
88
// Старые поля для обратной совместимости (тики)
99
private int messageLifetimeTicks = 80;
1010
private int messageFallTicks = 20;
@@ -22,6 +22,7 @@ public class ModConfigData {
2222
private MessageScale messageScale = MessageScale.NORMAL;
2323
private boolean showMessageBackground = true;
2424
private boolean followPlayer = false;
25+
private boolean enableClickToRemove = true;
2526

2627
// Геттеры
2728
public String getTwitchChannelName() { return twitchChannelName; }
@@ -40,6 +41,7 @@ public class ModConfigData {
4041
public MessageScale getMessageScale() { return messageScale; }
4142
public boolean isShowMessageBackground() { return showMessageBackground; }
4243
public boolean isFollowPlayer() { return followPlayer; }
44+
public boolean isEnableClickToRemove() { return enableClickToRemove; }
4345

4446
// Сеттеры
4547
public void setTwitchChannelName(String twitchChannelName) { this.twitchChannelName = twitchChannelName; }
@@ -58,6 +60,7 @@ public class ModConfigData {
5860
public void setMessageScale(MessageScale messageScale) { this.messageScale = messageScale; }
5961
public void setShowMessageBackground(boolean showMessageBackground) { this.showMessageBackground = showMessageBackground; }
6062
public void setFollowPlayer(boolean followPlayer) { this.followPlayer = followPlayer; }
63+
public void setEnableClickToRemove(boolean enableClickToRemove) { this.enableClickToRemove = enableClickToRemove; }
6164

6265
// Методы для обратной совместимости
6366
public boolean isMessagesInFrontOfPlayerOnly() {
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
package takeyourminestream.modid.messages;
2+
3+
import net.minecraft.client.MinecraftClient;
4+
import net.minecraft.client.font.TextRenderer;
5+
import net.minecraft.text.OrderedText;
6+
import net.minecraft.text.Text;
7+
import net.minecraft.util.hit.HitResult;
8+
import net.minecraft.util.math.Vec3d;
9+
import net.minecraft.util.math.Box;
10+
11+
import java.util.List;
12+
13+
/**
14+
* Обработчик кликов по сообщениям
15+
*/
16+
public class MessageClickHandler {
17+
private static final float CLICK_DISTANCE = 100.0f; // Максимальная дистанция для клика
18+
19+
/**
20+
* Проверяет, был ли клик по сообщению
21+
* @param client Minecraft клиент
22+
* @param message Сообщение для проверки
23+
* @param tickCounter Текущий счетчик тиков
24+
* @return true если клик попал по сообщению
25+
*/
26+
public static boolean isClickOnMessage(MinecraftClient client, Message message, int tickCounter) {
27+
if (client.player == null || client.crosshairTarget == null) {
28+
return false;
29+
}
30+
31+
// Проверяем дистанцию до сообщения
32+
Vec3d cameraPos = client.gameRenderer.getCamera().getPos();
33+
Vec3d messagePos = message.getPosition();
34+
double distance = cameraPos.distanceTo(messagePos);
35+
36+
if (distance > CLICK_DISTANCE) {
37+
return false;
38+
}
39+
40+
// Получаем направление взгляда
41+
Vec3d lookVec = client.player.getRotationVec(1.0f);
42+
Vec3d rayStart = cameraPos;
43+
Vec3d rayEnd = rayStart.add(lookVec.multiply(CLICK_DISTANCE));
44+
45+
// Вычисляем размеры сообщения
46+
TextRenderer textRenderer = client.textRenderer;
47+
List<OrderedText> wrappedText = textRenderer.wrapLines(Text.of(message.getText()), 120);
48+
49+
float totalTextHeight = wrappedText.size() * textRenderer.fontHeight;
50+
int maxTextWidth = 0;
51+
for (OrderedText line : wrappedText) {
52+
int w = textRenderer.getWidth(line);
53+
if (w > maxTextWidth) maxTextWidth = w;
54+
}
55+
56+
// Масштаб сообщения
57+
float baseScale = 0.025f;
58+
float configScale = takeyourminestream.modid.ModConfig.getMESSAGE_SCALE().getScale();
59+
float finalScale = baseScale * configScale;
60+
61+
// Размеры в мировых координатах
62+
float worldWidth = maxTextWidth * finalScale;
63+
float worldHeight = totalTextHeight * finalScale;
64+
65+
// Создаем bounding box вокруг сообщения
66+
// Учитываем ориентацию сообщения (yaw и pitch)
67+
Vec3d center = messagePos;
68+
69+
// Упрощенная проверка - используем сферу вокруг сообщения
70+
float radius = Math.max(worldWidth, worldHeight) / 2.0f;
71+
72+
// Проверяем пересечение луча со сферой
73+
Vec3d toCenter = center.subtract(rayStart);
74+
double projection = toCenter.dotProduct(lookVec);
75+
76+
if (projection < 0) {
77+
return false; // Сообщение позади камеры
78+
}
79+
80+
Vec3d closestPoint = rayStart.add(lookVec.multiply(projection));
81+
double distanceToRay = closestPoint.distanceTo(center);
82+
83+
return distanceToRay <= radius;
84+
}
85+
86+
/**
87+
* Проверяет, смотрит ли игрок на сообщение (более точная проверка)
88+
* @param client Minecraft клиент
89+
* @param message Сообщение для проверки
90+
* @return true если игрок смотрит на сообщение
91+
*/
92+
public static boolean isLookingAtMessage(MinecraftClient client, Message message) {
93+
if (client.player == null) {
94+
return false;
95+
}
96+
97+
Vec3d cameraPos = client.gameRenderer.getCamera().getPos();
98+
Vec3d messagePos = message.getPosition();
99+
double distance = cameraPos.distanceTo(messagePos);
100+
101+
if (distance > CLICK_DISTANCE) {
102+
return false;
103+
}
104+
105+
// Получаем направление взгляда
106+
Vec3d lookVec = client.player.getRotationVec(1.0f);
107+
Vec3d toMessage = messagePos.subtract(cameraPos).normalize();
108+
109+
// Проверяем угол между направлением взгляда и направлением к сообщению
110+
double dotProduct = lookVec.dotProduct(toMessage);
111+
double angleThreshold = Math.cos(Math.toRadians(10.0)); // 10 градусов
112+
113+
return dotProduct >= angleThreshold;
114+
}
115+
}

src/client/java/takeyourminestream/modid/messages/MessageLifecycleManager.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,24 @@ public int getMessageHistorySize() {
197197
public void clearMessageHistory() {
198198
messageHistory.clear();
199199
}
200+
201+
/**
202+
* Удаляет сообщение с немедленным спавном партиклов
203+
* @param message Сообщение для удаления
204+
* @param client Minecraft клиент
205+
*/
206+
public void removeMessageWithParticles(Message message, MinecraftClient client) {
207+
if (activeMessages.contains(message)) {
208+
// Спавним партиклы на текущей позиции
209+
if (particleManager != null) {
210+
MessageParticleSpawner.spawnParticlesForMessage(message, particleManager, client, message.getPosition());
211+
}
212+
213+
// Удаляем сообщение
214+
activeMessages.remove(message);
215+
spawnedParticlesForMessages.remove(message);
216+
}
217+
}
200218

201219
private static float lerpAngleDegrees(float a, float b, float t) {
202220
float delta = MathHelper.wrapDegrees(b - a);

0 commit comments

Comments
 (0)