Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import com.viaversion.viarewind.protocol.v1_9to1_8.storage.EntityTracker1_9;
import com.viaversion.viarewind.protocol.v1_9to1_8.storage.LevitationStorage;
import com.viaversion.viarewind.protocol.v1_9to1_8.storage.PlayerPositionTracker;
import com.viaversion.viarewind.protocol.v1_9to1_8.storage.LastTitle;
import com.viaversion.viarewind.protocol.v1_9to1_8.storage.WindowTracker;
import com.viaversion.viarewind.protocol.v1_9to1_8.task.CooldownIndicatorTask;
import com.viaversion.viarewind.protocol.v1_9to1_8.task.LevitationUpdateTask;
Expand Down Expand Up @@ -87,6 +88,7 @@ public void init(UserConnection connection) {
connection.put(new LevitationStorage());
connection.put(new PlayerPositionTracker());
connection.put(new CooldownStorage());
connection.put(new LastTitle());
connection.put(new BlockPlaceDestroyTracker());
connection.put(new BossBarStorage(connection));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,50 +18,95 @@
package com.viaversion.viarewind.protocol.v1_9to1_8.cooldown;

import com.viaversion.viarewind.protocol.v1_9to1_8.Protocol1_9To1_8;
import com.viaversion.viarewind.protocol.v1_9to1_8.storage.LastTitle;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.libs.gson.JsonPrimitive;
import com.viaversion.viaversion.protocols.v1_8to1_9.packet.ClientboundPackets1_8;
import java.util.function.Consumer;

public class TitleCooldownVisualization implements CooldownVisualization {

private static final int ACTION_SET_TITLE = 0;
private static final int ACTION_SET_SUBTITLE = 1;
private static final int ACTION_SET_TIMES_AND_DISPLAY = 2;
private static final int ACTION_HIDE = 3;
public static final int ACTION_SET_TITLE = 0;
public static final int ACTION_SET_SUBTITLE = 1;
public static final int ACTION_SET_TIMES_AND_DISPLAY = 2;
public static final int ACTION_HIDE = 3;
public static final int ACTION_RESET = 4;

private final UserConnection user;
private boolean visible;

public TitleCooldownVisualization(UserConnection user) {
this.user = user;
}

@Override
public void show(double progress) throws Exception {
final String text = CooldownVisualization.buildProgressText("˙", progress);

sendTitlePacket(ACTION_SET_TITLE, wrapper -> wrapper.write(Types.COMPONENT, new JsonPrimitive("")));
sendTitlePacket(ACTION_SET_SUBTITLE, wrapper -> wrapper.write(Types.COMPONENT, new JsonPrimitive(text)));
sendTitlePacket(ACTION_SET_TIMES_AND_DISPLAY, wrapper -> {
wrapper.write(Types.INT, 0);
wrapper.write(Types.INT, 2);
wrapper.write(Types.INT, 5);
});
final LastTitle title = this.user.get(LastTitle.class);
if (this.visible && title.isVisible()) {
this.restoreTitle(title);
return;
}

final PacketWrapper setTitle = PacketWrapper.create(ClientboundPackets1_8.SET_TITLES, user);
setTitle.write(Types.VAR_INT, ACTION_SET_TITLE);
setTitle.write(Types.COMPONENT, new JsonPrimitive(""));
setTitle.send(Protocol1_9To1_8.class);

final PacketWrapper setSubtitle = PacketWrapper.create(ClientboundPackets1_8.SET_TITLES, user);
setSubtitle.write(Types.VAR_INT, ACTION_SET_SUBTITLE);
setSubtitle.write(Types.COMPONENT, new JsonPrimitive(CooldownVisualization.buildProgressText("˙", progress)));
setSubtitle.send(Protocol1_9To1_8.class);

final PacketWrapper setTitleTimes = PacketWrapper.create(ClientboundPackets1_8.SET_TITLES, user);
setTitleTimes.write(Types.VAR_INT, ACTION_SET_TIMES_AND_DISPLAY);
setTitleTimes.write(Types.INT, 0);
setTitleTimes.write(Types.INT, 2);
setTitleTimes.write(Types.INT, 5);
setTitleTimes.send(Protocol1_9To1_8.class);
this.visible = true;
}

@Override
public void hide() throws Exception {
sendTitlePacket(ACTION_HIDE, wrapper -> {
});
if (!this.visible) {
return;
}

final LastTitle title = this.user.get(LastTitle.class);
if (title.isVisible()) {
this.restoreTitle(title);
return;
}

final PacketWrapper hideTitle = PacketWrapper.create(ClientboundPackets1_8.SET_TITLES, user);
hideTitle.write(Types.VAR_INT, ACTION_HIDE);
hideTitle.send(Protocol1_9To1_8.class);
this.visible = false;
}

private void sendTitlePacket(int action, Consumer<PacketWrapper> writer) {
final PacketWrapper title = PacketWrapper.create(ClientboundPackets1_8.SET_TITLES, user);
title.write(Types.VAR_INT, action);
writer.accept(title);
title.scheduleSend(Protocol1_9To1_8.class);
private void restoreTitle(final LastTitle title) {
final PacketWrapper setTitleTimes = PacketWrapper.create(ClientboundPackets1_8.SET_TITLES, user);
setTitleTimes.write(Types.VAR_INT, ACTION_SET_TIMES_AND_DISPLAY);
final int[] times = title.remainingTimes();
setTitleTimes.write(Types.INT, times[0]);
setTitleTimes.write(Types.INT, times[1]);
setTitleTimes.write(Types.INT, times[2]);
setTitleTimes.send(Protocol1_9To1_8.class);

if (title.subtitle() != null) {
final PacketWrapper setSubtitle = PacketWrapper.create(ClientboundPackets1_8.SET_TITLES, user);
setSubtitle.write(Types.VAR_INT, ACTION_SET_SUBTITLE);
setSubtitle.write(Types.COMPONENT, title.subtitle());
setSubtitle.send(Protocol1_9To1_8.class);
}

final PacketWrapper setTitle = PacketWrapper.create(ClientboundPackets1_8.SET_TITLES, user);
setTitle.write(Types.VAR_INT, ACTION_SET_TITLE);
setTitle.write(Types.COMPONENT, title.title());
setTitle.send(Protocol1_9To1_8.class);

this.visible = false;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@
import com.viaversion.nbt.tag.ListTag;
import com.viaversion.nbt.tag.StringTag;
import com.viaversion.viarewind.ViaRewind;
import com.viaversion.viarewind.api.type.RewindTypes;
import com.viaversion.viarewind.protocol.v1_9to1_8.Protocol1_9To1_8;
import com.viaversion.viarewind.protocol.v1_9to1_8.provider.InventoryProvider;
import com.viaversion.viarewind.protocol.v1_9to1_8.storage.BlockPlaceDestroyTracker;
import com.viaversion.viarewind.protocol.v1_9to1_8.storage.BossBarStorage;
import com.viaversion.viarewind.protocol.v1_9to1_8.storage.CooldownStorage;
import com.viaversion.viarewind.protocol.v1_9to1_8.storage.EntityTracker1_9;
import com.viaversion.viarewind.protocol.v1_9to1_8.storage.LastTitle;
import com.viaversion.viarewind.protocol.v1_9to1_8.storage.PlayerPositionTracker;
import com.viaversion.viarewind.utils.ChatUtil;
import com.viaversion.viaversion.api.Via;
Expand All @@ -43,7 +43,6 @@
import com.viaversion.viaversion.api.rewriter.RewriterBase;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.libs.gson.JsonElement;
import com.viaversion.viaversion.libs.gson.JsonParser;
import com.viaversion.viaversion.protocols.v1_8to1_9.packet.ClientboundPackets1_8;
import com.viaversion.viaversion.protocols.v1_8to1_9.packet.ClientboundPackets1_9;
import com.viaversion.viaversion.protocols.v1_8to1_9.packet.ServerboundPackets1_8;
Expand All @@ -53,6 +52,12 @@
import java.util.List;
import java.util.UUID;

import static com.viaversion.viarewind.protocol.v1_9to1_8.cooldown.TitleCooldownVisualization.ACTION_HIDE;
import static com.viaversion.viarewind.protocol.v1_9to1_8.cooldown.TitleCooldownVisualization.ACTION_RESET;
import static com.viaversion.viarewind.protocol.v1_9to1_8.cooldown.TitleCooldownVisualization.ACTION_SET_SUBTITLE;
import static com.viaversion.viarewind.protocol.v1_9to1_8.cooldown.TitleCooldownVisualization.ACTION_SET_TIMES_AND_DISPLAY;
import static com.viaversion.viarewind.protocol.v1_9to1_8.cooldown.TitleCooldownVisualization.ACTION_SET_TITLE;

public class PlayerPacketRewriter1_9 extends RewriterBase<Protocol1_9To1_8> {

public PlayerPacketRewriter1_9(Protocol1_9To1_8 protocol) {
Expand Down Expand Up @@ -107,6 +112,26 @@ public void register() {

protocol.cancelClientbound(ClientboundPackets1_9.COOLDOWN);

protocol.registerClientbound(ClientboundPackets1_9.SET_TITLES, wrapper -> {
final int action = wrapper.passthrough(Types.VAR_INT);
if (action == ACTION_SET_TITLE) {
final JsonElement title = wrapper.passthrough(Types.COMPONENT);
wrapper.user().get(LastTitle.class).setTitle(title);
} else if (action == ACTION_SET_SUBTITLE) {
final JsonElement subtitle = wrapper.passthrough(Types.COMPONENT);
wrapper.user().get(LastTitle.class).setSubtitle(subtitle);
} else if (action == ACTION_SET_TIMES_AND_DISPLAY) {
final int fadeIn = wrapper.passthrough(Types.INT);
final int stay = wrapper.passthrough(Types.INT);
final int fadeOut = wrapper.passthrough(Types.INT);
wrapper.user().get(LastTitle.class).setTimes(fadeIn, stay, fadeOut);
} else if (action == ACTION_HIDE) {
wrapper.user().get(LastTitle.class).hide();
} else if (action == ACTION_RESET) {
wrapper.user().get(LastTitle.class).reset();
}
});

protocol.registerClientbound(ClientboundPackets1_9.CUSTOM_PAYLOAD, new PacketHandlers() {
@Override
public void register() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.v1_9to1_8.storage;

import com.viaversion.viaversion.api.connection.StorableObject;
import com.viaversion.viaversion.libs.gson.JsonElement;

public final class LastTitle implements StorableObject {

private JsonElement title;
private JsonElement subtitle;

private long visibleSince;
private long visibleUntil;

private int fadeIn;
private int stay;
private int fadeOut;

public LastTitle() {
this.reset();
}

public void setTitle(final JsonElement title) {
this.title = title;

final long now = System.currentTimeMillis();
this.visibleSince = now;
this.visibleUntil = now + titleLength();
}

public void setSubtitle(final JsonElement subtitle) {
this.subtitle = subtitle;
}

public void setTimes(final int fadeIn, final int stay, final int fadeOut) {
this.fadeIn = fadeIn;
this.stay = stay;
this.fadeOut = fadeOut;

if (this.visibleUntil > System.currentTimeMillis()) {
final long now = System.currentTimeMillis();
this.visibleSince = now;
this.visibleUntil = now + titleLength();
}
}

public void hide() {
this.visibleSince = 0;
this.visibleUntil = 0;
}

public void reset() {
this.hide();

this.fadeIn = 10;
this.stay = 70;
this.fadeOut = 20;
}

public boolean isVisible() {
return this.title != null && this.visibleUntil > System.currentTimeMillis();
}

public JsonElement title() {
return this.title;
}

public JsonElement subtitle() {
return this.subtitle;
}

public int[] remainingTimes() {
final int fullLength = Math.max(0, this.fadeIn + this.stay + this.fadeOut);
final int elapsed = (int) Math.min(fullLength, Math.max(0, (System.currentTimeMillis() - this.visibleSince) / 50L));
if (elapsed < this.fadeIn) {
return new int[]{this.fadeIn - elapsed, this.stay, this.fadeOut};
}

final int titleEnd = this.fadeIn + this.stay;
if (elapsed < titleEnd) {
return new int[]{0, titleEnd - elapsed, this.fadeOut};
}

return new int[]{0, 0, fullLength - elapsed};
}

private long titleLength() {
return Math.max(0, this.fadeIn + this.stay + this.fadeOut) * 50L;
}

}