1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
|
/*
* Copyright (C) 2023 NotEnoughUpdates contributors
*
* This file is part of NotEnoughUpdates.
*
* NotEnoughUpdates is free software: you can redistribute it
* and/or modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation, either
* version 3 of the License, or (at your option) any later version.
*
* NotEnoughUpdates 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
*/
package io.github.moulberry.notenoughupdates.miscfeatures.world;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
import io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSubscribe;
import io.github.moulberry.notenoughupdates.core.util.render.RenderUtils;
import io.github.moulberry.notenoughupdates.util.SBInfo;
import io.github.moulberry.notenoughupdates.util.SpecialColour;
import lombok.val;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.init.Blocks;
import net.minecraft.network.play.server.S22PacketMultiBlockChange;
import net.minecraft.network.play.server.S23PacketBlockChange;
import net.minecraft.util.BlockPos;
import net.minecraft.util.Vec3;
import net.minecraft.world.World;
import net.minecraftforge.client.event.RenderWorldLastEvent;
import net.minecraftforge.event.entity.player.PlayerInteractEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.gameevent.TickEvent;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
@NEUAutoSubscribe
public class CrystalHollowChestHighlighter extends GenericBlockHighlighter {
// Because ConcurrentModificationException is the bane of me
public static CopyOnWriteArrayList<BlockPos> markedBlocks = new CopyOnWriteArrayList<>();
public static void processBlockChangePacket(S23PacketBlockChange packetIn) {
BlockPos pos = packetIn.getBlockPosition();
if (packetIn.blockState == null) return;
checkForChest(pos, packetIn.blockState);
}
public static void processMultiBlockChangePacket(S22PacketMultiBlockChange packetIn) {
for (S22PacketMultiBlockChange.BlockUpdateData blockChanged : packetIn.getChangedBlocks()) {
BlockPos pos = blockChanged.getPos();
checkForChest(pos, blockChanged.getBlockState());
}
}
public static void checkForChest(BlockPos pos, IBlockState blockState) {
val world = Minecraft.getMinecraft().theWorld;
val player = Minecraft.getMinecraft().thePlayer;
if (world == null || player == null) return;
IBlockState oldState = world.getBlockState(pos);
if ((oldState.getBlock() == Blocks.air || oldState.getBlock() == Blocks.stone) &&
blockState.getBlock() == Blocks.chest) {
// Only add if in a 10x10x10 area. Minimises other players' chests being caught
if (player.getEntityBoundingBox().expand(10, 10, 10).isVecInside(new Vec3(pos))) {
markedBlocks.add(pos);
}
}
}
@SubscribeEvent
public void onTick(TickEvent.ClientTickEvent event) {
if (!isEnabled()) return;
markedBlocks.forEach(this::tryRegisterInterest);
// Here to catch chests that get highlighted by other people after they open them, and
// any highlighted blocks in which the chest despawned in
List<BlockPos> blockToRemove = new ArrayList<>();
highlightedBlocks.forEach(it -> {
if (Minecraft.getMinecraft().theWorld.getBlockState(it).getBlock() != Blocks.chest) {
blockToRemove.add(it);
}
});
blockToRemove.forEach(highlightedBlocks::remove);
blockToRemove.forEach(markedBlocks::remove);
}
@SubscribeEvent
public void onBlockInteraction(PlayerInteractEvent event) {
if (event.action == PlayerInteractEvent.Action.RIGHT_CLICK_BLOCK) {
markedBlocks.remove(event.pos);
highlightedBlocks.remove(event.pos);
}
}
@Override
public void onWorldRenderLast(RenderWorldLastEvent event) {
if (!isEnabled()) return;
World w = Minecraft.getMinecraft().theWorld;
if (w == null) return;
for (BlockPos blockPos : highlightedBlocks) {
RenderUtils.renderBoundingBox(blockPos, getColor(blockPos), event.partialTicks, false);
}
}
@Override
protected boolean isEnabled() {
return "crystal_hollows".equals(SBInfo.getInstance().getLocation()) &&
NotEnoughUpdates.INSTANCE.config.world.highlightCrystalHollowChests;
}
@Override
protected boolean isValidHighlightSpot(BlockPos key) {
World w = Minecraft.getMinecraft().theWorld;
if (w == null) return false;
Block b = w.getBlockState(key).getBlock();
return b == Blocks.chest;
}
@Override
protected int getColor(BlockPos blockPos) {
return SpecialColour.specialToChromaRGB(NotEnoughUpdates.INSTANCE.config.world.crystalHollowChestColor);
}
}
|