Skip to content

Commit 20055f2

Browse files
committed
Colors are indices now
Technically this makes the actual colors a client concern. However, it also allows the client to have a different color palette an easy way. The main reason for doing this however, was reducing payload size, in preparation for the drawing gallery, to reduce memory usage when saving drawings and potentially persisting them. We might also change this to a binary format, as it'll be much smaller, given the amount of JSON overhead. A minimum line event will currently have a size of 70b, while in binary, it would only have 11 bytes, if we don't microoptimise (less is possible).
1 parent f688fb5 commit 20055f2

File tree

5 files changed

+212
-254
lines changed

5 files changed

+212
-254
lines changed

internal/api/v1.go

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -356,15 +356,10 @@ func (handler *V1Handler) getStats(writer http.ResponseWriter, _ *http.Request)
356356
}
357357
}
358358

359-
var (
360-
// CanvasColor is the initially / empty canvas colors value used for
361-
// Lobbydata objects.
362-
CanvasColor = game.RGBColor{R: 255, G: 255, B: 255}
363-
// SuggestedBrushSizes is suggested brush sizes value used for
364-
// Lobbydata objects. A unit test makes sure these values are ordered
365-
// and within the specified bounds.
366-
SuggestedBrushSizes = [4]uint8{8, 16, 24, 32}
367-
)
359+
// SuggestedBrushSizes is suggested brush sizes value used for
360+
// Lobbydata objects. A unit test makes sure these values are ordered
361+
// and within the specified bounds.
362+
var SuggestedBrushSizes = [4]uint8{8, 16, 24, 32}
368363

369364
// LobbyData is the data necessary for correctly configuring a lobby.
370365
// While unofficial clients will probably need all of these values, the
@@ -385,7 +380,7 @@ type LobbyData struct {
385380
// MaxBrushSize is the maximum amount of pixels the brush can draw in.
386381
MaxBrushSize int `json:"maxBrushSize"`
387382
// CanvasColor is the initially (empty) color of the canvas.
388-
CanvasColor game.RGBColor `json:"canvasColor"`
383+
CanvasColor uint8 `json:"canvasColor"`
389384
// SuggestedBrushSizes are suggestions for the different brush sizes
390385
// that the user can choose between. These brushes are guaranteed to
391386
// be ordered from low to high and stay with the bounds.
@@ -403,7 +398,7 @@ func CreateLobbyData(lobby *game.Lobby) *LobbyData {
403398
DrawingBoardBaseHeight: game.DrawingBoardBaseHeight,
404399
MinBrushSize: game.MinBrushSize,
405400
MaxBrushSize: game.MaxBrushSize,
406-
CanvasColor: CanvasColor,
401+
CanvasColor: 0, /* White */
407402
SuggestedBrushSizes: SuggestedBrushSizes,
408403
}
409404
}

internal/api/v1_easyjson.go

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/frontend/templates/lobby.html

Lines changed: 83 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -264,59 +264,59 @@
264264
to prevent hover and active colors to appear. -->
265265
<div class="color-button-row">
266266
<button class="color-button" style="background-color: #ffffff !Important"
267-
onmousedown="setColor('#ffffff')" onclick="setColor('#ffffff')"></button>
267+
onmousedown="setColor(0)" onclick="setColor(0)"></button>
268268
<button class="color-button" style="background-color: #c1c1c1 !Important"
269-
onmousedown="setColor('#c1c1c1')" onclick="setColor('#c1c1c1')"></button>
269+
onmousedown="setColor(1)" onclick="setColor(1)"></button>
270270
<button class="color-button" style="background-color: #ef130b !Important"
271-
onmousedown="setColor('#ef130b')" onclick="setColor('#ef130b')"></button>
271+
onmousedown="setColor(2)" onclick="setColor(2)"></button>
272272
<button class="color-button" style="background-color: #ff7100 !Important"
273-
onmousedown="setColor('#ff7100')" onclick="setColor('#ff7100')"></button>
273+
onmousedown="setColor(3)" onclick="setColor(3)"></button>
274274
<button class="color-button" style="background-color: #ffe400 !Important"
275-
onmousedown="setColor('#ffe400')" onclick="setColor('#ffe400')"></button>
275+
onmousedown="setColor(4)" onclick="setColor(4)"></button>
276276
<button class="color-button" style="background-color: #00cc00 !Important"
277-
onmousedown="setColor('#00cc00')" onclick="setColor('#00cc00')"></button>
277+
onmousedown="setColor(5)" onclick="setColor(5)"></button>
278278
<button class="color-button" style="background-color: #00b2ff !Important"
279-
onmousedown="setColor('#00b2ff')" onclick="setColor('#00b2ff')"></button>
279+
onmousedown="setColor(6)" onclick="setColor(6)"></button>
280280
<button class="color-button" style="background-color: #231fd3 !Important"
281-
onmousedown="setColor('#231fd3')" onclick="setColor('#231fd3')"></button>
281+
onmousedown="setColor(7)" onclick="setColor(7)"></button>
282282
<button class="color-button" style="background-color: #a300ba !Important"
283-
onmousedown="setColor('#a300ba')" onclick="setColor('#a300ba')"></button>
283+
onmousedown="setColor(8)" onclick="setColor(8)"></button>
284284
<button class="color-button" style="background-color: #d37caa !Important"
285-
onmousedown="setColor('#d37caa')" onclick="setColor('#d37caa')"></button>
285+
onmousedown="setColor(9)" onclick="setColor(9)"></button>
286286
<button class="color-button" style="background-color: #a0522d !Important"
287-
onmousedown="setColor('#a0522d')" onclick="setColor('#a0522d')"></button>
287+
onmousedown="setColor(10)" onclick="setColor(10)"></button>
288288
<button class="color-button" style="background-color: #592f2a !Important"
289-
onmousedown="setColor('#592f2a')" onclick="setColor('#592f2a')"></button>
289+
onmousedown="setColor(11)" onclick="setColor(11)"></button>
290290
<button class="color-button" style="background-color: #ecbcb4 !Important"
291-
onmousedown="setColor('#ecbcb4')" onclick="setColor('#ecbcb4')"></button>
291+
onmousedown="setColor(12)" onclick="setColor(12)"></button>
292292
</div>
293293
<div class="color-button-row">
294294
<button class="color-button" style="background-color: #000000 !Important"
295-
onmousedown="setColor('#000000')" onclick="setColor('#000000')"></button>
295+
onmousedown="setColor(13)" onclick="setColor(13)"></button>
296296
<button class="color-button" style="background-color: #4c4c4c !Important"
297-
onmousedown="setColor('#4c4c4c')" onclick="setColor('#4c4c4c')"></button>
297+
onmousedown="setColor(14)" onclick="setColor(14)"></button>
298298
<button class="color-button" style="background-color: #740b07 !Important"
299-
onmousedown="setColor('#740b07')" onclick="setColor('#740b07')"></button>
299+
onmousedown="setColor(15)" onclick="setColor(15)"></button>
300300
<button class="color-button" style="background-color: #c23800 !Important"
301-
onmousedown="setColor('#c23800')" onclick="setColor('#c23800')"></button>
301+
onmousedown="setColor(16)" onclick="setColor(16)"></button>
302302
<button class="color-button" style="background-color: #e8a200 !Important"
303-
onmousedown="setColor('#e8a200')" onclick="setColor('#e8a200')"></button>
303+
onmousedown="setColor(17)" onclick="setColor(17)"></button>
304304
<button class="color-button" style="background-color: #005510 !Important"
305-
onmousedown="setColor('#005510')" onclick="setColor('#005510')"></button>
305+
onmousedown="setColor(18)" onclick="setColor(18)"></button>
306306
<button class="color-button" style="background-color: #00569e !Important"
307-
onmousedown="setColor('#00569e')" onclick="setColor('#00569e')"></button>
307+
onmousedown="setColor(19)" onclick="setColor(19)"></button>
308308
<button class="color-button" style="background-color: #0e0865 !Important"
309-
onmousedown="setColor('#0e0865')" onclick="setColor('#0e0865')"></button>
309+
onmousedown="setColor(20)" onclick="setColor(20)"></button>
310310
<button class="color-button" style="background-color: #550069 !Important"
311-
onmousedown="setColor('#550069')" onclick="setColor('#550069')"></button>
311+
onmousedown="setColor(21)" onclick="setColor(21)"></button>
312312
<button class="color-button" style="background-color: #a75574 !Important"
313-
onmousedown="setColor('#a75574')" onclick="setColor('#a75574')"></button>
313+
onmousedown="setColor(22)" onclick="setColor(22)"></button>
314314
<button class="color-button" style="background-color: #63300d !Important"
315-
onmousedown="setColor('#63300d')" onclick="setColor('#63300d')"></button>
315+
onmousedown="setColor(23)" onclick="setColor(23)"></button>
316316
<button class="color-button" style="background-color: #492f31 !Important"
317-
onmousedown="setColor('#492f31')" onclick="setColor('#492f31')"></button>
317+
onmousedown="setColor(24)" onclick="setColor(24)"></button>
318318
<button class="color-button" style="background-color: #d1a3a4 !Important"
319-
onmousedown="setColor('#d1a3a4')" onclick="setColor('#d1a3a4')"></button>
319+
onmousedown="setColor(25)" onclick="setColor(25)"></button>
320320
</div>
321321
</div>
322322
<!--The following buttons als override onmousedown and onmouseup to make
@@ -555,6 +555,35 @@
555555
let sound = localStorage.getItem("sound") !== "false";
556556
updateSoundIcon();
557557

558+
const colorMap = [
559+
{hex: '#ffffff', rgb: hexStringToRgbColorObject('#ffffff')},
560+
{hex: '#c1c1c1', rgb: hexStringToRgbColorObject('#c1c1c1')},
561+
{hex: '#ef130b', rgb: hexStringToRgbColorObject('#ef130b')},
562+
{hex: '#ff7100', rgb: hexStringToRgbColorObject('#ff7100')},
563+
{hex: '#ffe400', rgb: hexStringToRgbColorObject('#ffe400')},
564+
{hex: '#00cc00', rgb: hexStringToRgbColorObject('#00cc00')},
565+
{hex: '#00b2ff', rgb: hexStringToRgbColorObject('#00b2ff')},
566+
{hex: '#231fd3', rgb: hexStringToRgbColorObject('#231fd3')},
567+
{hex: '#a300ba', rgb: hexStringToRgbColorObject('#a300ba')},
568+
{hex: '#d37caa', rgb: hexStringToRgbColorObject('#d37caa')},
569+
{hex: '#a0522d', rgb: hexStringToRgbColorObject('#a0522d')},
570+
{hex: '#592f2a', rgb: hexStringToRgbColorObject('#592f2a')},
571+
{hex: '#ecbcb4', rgb: hexStringToRgbColorObject('#ecbcb4')},
572+
{hex: '#000000', rgb: hexStringToRgbColorObject('#000000')},
573+
{hex: '#4c4c4c', rgb: hexStringToRgbColorObject('#4c4c4c')},
574+
{hex: '#740b07', rgb: hexStringToRgbColorObject('#740b07')},
575+
{hex: '#c23800', rgb: hexStringToRgbColorObject('#c23800')},
576+
{hex: '#e8a200', rgb: hexStringToRgbColorObject('#e8a200')},
577+
{hex: '#005510', rgb: hexStringToRgbColorObject('#005510')},
578+
{hex: '#00569e', rgb: hexStringToRgbColorObject('#00569e')},
579+
{hex: '#0e0865', rgb: hexStringToRgbColorObject('#0e0865')},
580+
{hex: '#550069', rgb: hexStringToRgbColorObject('#550069')},
581+
{hex: '#a75574', rgb: hexStringToRgbColorObject('#a75574')},
582+
{hex: '#63300d', rgb: hexStringToRgbColorObject('#63300d')},
583+
{hex: '#492f31', rgb: hexStringToRgbColorObject('#492f31')},
584+
{hex: '#d1a3a4', rgb: hexStringToRgbColorObject('#d1a3a4')}
585+
];
586+
558587
const set_dummy_word_hints = () => {
559588
// Dummy wordhint to prevent layout changes.
560589
applyWordHints([{
@@ -881,13 +910,18 @@
881910
chooseToolNoUpdate(rubber);
882911
}
883912

884-
let localColor;
885-
setColorNoUpdate(sessionStorage.getItem("local_color") ?? "#000000");
913+
let localColor, localColorIndex;
886914

887-
updateDrawingStateUI();
915+
function indexToHexColor(index) {
916+
return colorMap[index].hex;
917+
}
888918

889-
function setColor(colorAsHex) {
890-
setColorNoUpdate(colorAsHex);
919+
function indexToRgbColor(index) {
920+
return colorMap[index].rgb;
921+
}
922+
923+
function setColor(index) {
924+
setColorNoUpdate(index);
891925

892926
// If we select a new color, we assume we don't want to use the
893927
// rubber anymore and automatically switch to the pen.
@@ -902,11 +936,15 @@
902936
}
903937
}
904938

905-
function setColorNoUpdate(colorAsHex) {
906-
localColor = hexStringToRgbColorObject(colorAsHex);
907-
sessionStorage.setItem("local_color", colorAsHex);
939+
function setColorNoUpdate(index) {
940+
localColorIndex = index;
941+
localColor = indexToRgbColor(index);
942+
sessionStorage.setItem("local_color", JSON.stringify(index));
908943
}
909944

945+
setColorNoUpdate(JSON.parse(sessionStorage.getItem("local_color")) ?? 13 /* black*/);
946+
updateDrawingStateUI();
947+
910948
function setLineWidth(value) {
911949
setLineWidthNoUpdate(value);
912950
updateDrawingStateUI();
@@ -1242,14 +1280,15 @@
12421280
appendMessage("non-guessing-player-message", parsed.data.author, parsed.data.content);
12431281
} else if (parsed.type === "line") {
12441282
drawLine(context, parsed.data.x, parsed.data.y,
1245-
parsed.data.x2, parsed.data.y2, parsed.data.color,
1283+
parsed.data.x2, parsed.data.y2,
1284+
indexToRgbColor(parsed.data.color),
12461285
parsed.data.width);
12471286
} else if (parsed.type === "fill") {
12481287
if (floodfillUint8ClampedArray(
12491288
imageData.data,
12501289
parsed.data.x,
12511290
parsed.data.y,
1252-
parsed.data.color,
1291+
indexToRgbColor(parsed.data.color),
12531292
imageData.width,
12541293
imageData.height)) {
12551294
context.putImageData(imageData, 0, 0);
@@ -1771,13 +1810,13 @@
17711810
floodfillUint8ClampedArray(
17721811
imageData.data,
17731812
drawData.x, drawData.y,
1774-
drawData.color,
1813+
indexToRgbColor(drawData.color),
17751814
imageData.width, imageData.height);
17761815
} else if (drawElement.type === "line") {
17771816
_drawLine(
17781817
drawData.x, drawData.y,
17791818
drawData.x2, drawData.y2,
1780-
drawData.color,
1819+
indexToRgbColor(drawData.color),
17811820
drawData.width);
17821821
} else {
17831822
console.log("Unknown draw element type: " + drawData.type);
@@ -1874,7 +1913,7 @@
18741913
//clicked and 0 won't be the uninitialized state.
18751914
if (allowDrawing && event.button === 0) {
18761915
if (localTool === fillBucket) {
1877-
fillAndSendEvent(context, event.offsetX, event.offsetY, localColor);
1916+
fillAndSendEvent(context, event.offsetX, event.offsetY, localColorIndex);
18781917
} else {
18791918
drawLineAndSendEvent(context, event.offsetX, event.offsetY, event.offsetX, event.offsetY);
18801919
}
@@ -1973,17 +2012,18 @@
19732012
// Clear initially, as it will be black otherwise.
19742013
clear(context);
19752014

1976-
function fillAndSendEvent(context, x, y, color) {
2015+
function fillAndSendEvent(context, x, y, colorIndex) {
19772016
const xScaled = convertToServerCoordinate(x);
19782017
const yScaled = convertToServerCoordinate(y);
2018+
const color = indexToRgbColor(colorIndex);
19792019
if (floodfillUint8ClampedArray(imageData.data, xScaled, yScaled, color, imageData.width, imageData.height)) {
19802020
context.putImageData(imageData, 0, 0);
19812021
const fillInstruction = {
19822022
type: "fill",
19832023
data: {
19842024
x: xScaled,
19852025
y: yScaled,
1986-
color: color
2026+
color: colorIndex,
19872027
},
19882028
};
19892029
socket.send(JSON.stringify(fillInstruction));
@@ -1992,6 +2032,7 @@
19922032

19932033
function drawLineAndSendEvent(context, x1, y1, x2, y2) {
19942034
const color = localTool === rubber ? rubberColor : localColor;
2035+
const colorIndex = localTool === rubber ? 0 /* white */ : localColorIndex;
19952036

19962037
const x1Scaled = convertToServerCoordinate(x1);
19972038
const y1Scaled = convertToServerCoordinate(y1);
@@ -2007,7 +2048,7 @@
20072048
y: y1Scaled,
20082049
x2: x2Scaled,
20092050
y2: y2Scaled,
2010-
color: color,
2051+
color: colorIndex,
20112052
width: localLineWidth,
20122053
}
20132054
};

internal/game/shared.go

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -94,30 +94,32 @@ type WordHint struct {
9494
Underline bool `json:"underline"`
9595
}
9696

97-
// RGBColor represents a 24-bit color consisting of red, green and blue.
98-
type RGBColor struct {
99-
R uint8 `json:"r"`
100-
G uint8 `json:"g"`
101-
B uint8 `json:"b"`
102-
}
103-
10497
type LineEvent struct {
10598
Type string `json:"type"`
99+
// Data contains the coordinates, stroke width and color. The coors here
100+
// aren't uint16, as it allows us to easily allow implementing drawing on
101+
// the client, where the user drags the line over the canvas border.
102+
// If we were to not accept out of bounds values, the lines would be chopped
103+
// off before reaching the canvas border.
106104
Data struct {
107-
X int16 `json:"x"`
108-
Y int16 `json:"y"`
109-
X2 int16 `json:"x2"`
110-
Y2 int16 `json:"y2"`
111-
Color RGBColor `json:"color"`
112-
Width uint8 `json:"width"`
105+
X int16 `json:"x"`
106+
Y int16 `json:"y"`
107+
X2 int16 `json:"x2"`
108+
Y2 int16 `json:"y2"`
109+
// Color is a color index. This was previously an rgb value, but since
110+
// the values are always the same, using an index saves bandwidth.
111+
Color uint8 `json:"color"`
112+
Width uint8 `json:"width"`
113113
} `json:"data"`
114114
}
115115

116116
type FillEvent struct {
117117
Data *struct {
118-
X uint16 `json:"x"`
119-
Y uint16 `json:"y"`
120-
Color RGBColor `json:"color"`
118+
X uint16 `json:"x"`
119+
Y uint16 `json:"y"`
120+
// Color is a color index. This was previously an rgb value, but since
121+
// the values are always the same, using an index saves bandwidth.
122+
Color uint8 `json:"color"`
121123
} `json:"data"`
122124
Type string `json:"type"`
123125
}

0 commit comments

Comments
 (0)