aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/gregtech/common/WirelessComputationPacket.java
blob: e4d3fcb328278872ac7c40cb3e04cb0700dd96a1 (plain)
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
package gregtech.common;

import static gregtech.common.misc.GlobalVariableStorage.GlobalWirelessComputation;

import java.util.UUID;

import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
import gregtech.common.misc.spaceprojects.SpaceProjectManager;
import tectech.mechanics.dataTransport.QuantumDataPacket;

public class WirelessComputationPacket {

    public boolean wirelessEnabled = false;

    // The main idea: 'Clearing' the computation net advances the index and sets the computation stored
    // for this index to zero. Uploading is always done to the current index, downloading is always done from the
    // other index. This is essentially just a double buffered computation storage. The reason for this is that
    // every upload needs to be done before every download happens.
    private final long[] computationStored = new long[] { 0, 0 };
    private int currentIndex = 0;
    private long lastUpdateTick = -1;

    private int uploadIndex() {
        return currentIndex;
    }

    private int downloadIndex() {
        return (currentIndex + 1) % 2;
    }

    public long getAvailableComputationStored() {
        return computationStored[downloadIndex()];
    }

    private QuantumDataPacket download(long dataIn, long aTick) {
        if (!wirelessEnabled) return new QuantumDataPacket(0L);

        // If the net hasn't been updated yet this tick, make sure to do so
        if (lastUpdateTick < aTick) {
            this.update();
            lastUpdateTick = aTick;
        }

        // If we have enough computation 'stored', download it
        // Note that this means that if you do not have enough computation to go to all
        // destinations, it won't be distributed equally. This is fine.
        // This also means that if you don't have enough computation for a hatch, it will not receive any computation
        // at all. This is also fine.
        if (getAvailableComputationStored() >= dataIn) {
            computationStored[downloadIndex()] -= dataIn;
            return new QuantumDataPacket(dataIn);
        } else return new QuantumDataPacket(0L);
    }

    private void update() {
        // The reason we want this complex index cycling system is because hatches may upload and download computation
        // in the same tick as the currently stored computation is cleared. To avoid interruptions, we want to
        // try to double buffer these updates. This means that we keep two computation values around, and every update
        // we only clear one of them.

        // Remove downloaded computation previous index (which is also the next index since there are only two),
        // then remove the leftover from current index.
        computationStored[downloadIndex()] = 0;
        currentIndex = (currentIndex + 1) % 2;
    }

    private void setWirelessEnabled(boolean wirelessEnabled) {
        this.wirelessEnabled = wirelessEnabled;
    }

    private void upload(long dataOut, long aTick) {
        // If the net hasn't been updated yet this tick, make sure to do so
        if (lastUpdateTick < aTick) {
            this.update();
            lastUpdateTick = aTick;
        }
        // Store computation that is uploaded internally
        computationStored[uploadIndex()] += dataOut;
    }

    public static QuantumDataPacket downloadData(UUID userId, long dataIn, long aTick) {
        return getPacketByUserId(userId).download(dataIn, aTick);
    }

    public static void uploadData(UUID userId, long dataOut, long aTick) {
        getPacketByUserId(userId).upload(dataOut, aTick);
    }

    public static void enableWirelessNetWork(IGregTechTileEntity entity) {
        getPacketByUserId(entity.getOwnerUuid()).setWirelessEnabled(true);
    }

    public static void disableWirelessNetWork(IGregTechTileEntity entity) {
        getPacketByUserId(entity.getOwnerUuid()).setWirelessEnabled(false);
    }

    public static WirelessComputationPacket getPacketByUserId(UUID userId) {
        UUID team = SpaceProjectManager.getLeader(userId);
        if (GlobalWirelessComputation.get(team) == null) {
            GlobalWirelessComputation.put(team, new WirelessComputationPacket());
        }
        return GlobalWirelessComputation.get(team);
    }
}