Skip to content

Commit 8249a48

Browse files
committed
1 parent 8a08b4d commit 8249a48

File tree

7 files changed

+281
-5
lines changed

7 files changed

+281
-5
lines changed

index.html

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<!DOCTYPE html>
22
<html>
33
<head>
4-
<title>Prismarine Viewer</title>
4+
<title>Prismarine Web Client</title>
55
<style type="text/css">
66
html {
77
overflow: hidden;
@@ -22,9 +22,56 @@
2222
margin: 0;
2323
padding: 0;
2424
}
25+
.chat-wrapper {
26+
position: fixed;
27+
background-color: rgba(0, 0, 0, 0.5);
28+
}
29+
30+
.chat-display-wrapper {
31+
bottom: calc(8px * 16);
32+
padding: 4px;
33+
max-height: calc(90px * 8);
34+
width: calc(320px * 4);
35+
}
36+
37+
.chat-input-wrapper {
38+
bottom: calc(2px * 16);
39+
width: 100%;
40+
overflow: scroll;
41+
background-color: rgba(0, 0, 0, 0);
42+
}
43+
44+
.chat {
45+
overflow: scroll;
46+
color: white;
47+
font-size: 32px;
48+
margin: 0px;
49+
line-height: 100%;
50+
text-shadow: 4px 4px 0px #3f3f3f;
51+
font-family: minecraft, monospace;
52+
width: 100%;
53+
max-height: calc(90px * 8)
54+
}
55+
56+
input[type=text] {
57+
background-color: rgba(0, 0, 0, 0.5);
58+
}
59+
li {
60+
display: block;
61+
}
2562
</style>
2663
</head>
2764
<body>
65+
<div class="chat-wrapper chat-display-wrapper">
66+
<div class="chat" id="chat">
67+
<p>Welcome to prismarine-web-client! Chat appears here.</p>
68+
</div>
69+
</div>
70+
<div class="chat-wrapper chat-input-wrapper">
71+
<div class="chat" id="chat-input">
72+
<input type="text" class="chat" id="chatinput"></input>
73+
</div>
74+
</div>
2875
<script type="text/javascript" src="index.js"></script>
2976
</body>
3077
</html>

index.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ process.versions.node = '14.0.0'
66
const mineflayer = require('mineflayer')
77
const { WorldView, Viewer } = require('prismarine-viewer/viewer')
88
global.THREE = require('three')
9+
const chat = require('./lib/chat')
910

1011
async function main () {
1112
const viewDistance = 6
@@ -42,6 +43,8 @@ async function main () {
4243
renderer.setSize(window.innerWidth, window.innerHeight)
4344
document.body.appendChild(renderer.domElement)
4445

46+
chat.init(undefined, bot._client, renderer)
47+
4548
// Create viewer
4649
const viewer = new Viewer(renderer)
4750
viewer.setVersion(version)

lib/chat.js

Lines changed: 226 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,226 @@
1+
const styles = {
2+
black: 'color:#000000',
3+
dark_blue: 'color:#0000AA',
4+
dark_green: 'color:#00AA00',
5+
dark_aqua: 'color:#00AAAA',
6+
dark_red: 'color:#AA0000',
7+
dark_purple: 'color:#AA00AA',
8+
gold: 'color:#FFAA00',
9+
gray: 'color:#AAAAAA',
10+
dark_gray: 'color:#555555',
11+
blue: 'color:#5555FF',
12+
green: 'color:#55FF55',
13+
aqua: 'color:#55FFFF',
14+
red: 'color:#FF5555',
15+
light_purple: 'color:#FF55FF',
16+
yellow: 'color:#FFFF55',
17+
white: 'color:#FFFFFF',
18+
bold: 'font-weight:900',
19+
strikethrough: 'text-decoration:line-through',
20+
underlined: 'text-decoration:underline',
21+
italic: 'font-style:italic'
22+
}
23+
const dictionary = {
24+
'chat.stream.emote': '(%s) * %s %s',
25+
'chat.stream.text': '(%s) <%s> %s',
26+
// 'chat.type.achievement': '%s has just earned the achievement %s', // 1.8? Not tested
27+
// 'chat.type.advancement.task': '%s has just earned the advancement %s',
28+
// 'chat.type.advancement.goal': '%s has just reached the goal %s',
29+
// 'chat.type.advancement.challenge': '%s did a challenge lolol %s',
30+
'chat.type.admin': '[%s: %s]',
31+
'chat.type.announcement': '[%s] %s',
32+
'chat.type.emote': '* %s %s',
33+
'chat.type.text': '<%s> %s'
34+
}
35+
36+
export function init (mineweb, client, renderer) {
37+
const chat = document.querySelector('#chat')
38+
const chatInput = document.querySelector('#chatinput')
39+
40+
const chatHistory = []
41+
let chatHistoryPos = 0
42+
43+
renderer.domElement.requestPointerLock = renderer.domElement.requestPointerLock ||
44+
renderer.domElement.mozRequestPointerLock ||
45+
renderer.domElement.webkitRequestPointerLock
46+
47+
// Show chat
48+
chat.style.display = 'block'
49+
50+
let inChat = false
51+
// Esc event - Doesnt work with onkeypress?!
52+
document.onkeydown = function (e) {
53+
if (!inChat) return
54+
e = e || window.event
55+
if (e.keyCode === 27 || e.key === 'Escape' || e.key === 'Esc') {
56+
disableChat()
57+
} else if (e.keyCode === 38) {
58+
if (chatHistoryPos === 0) return
59+
chatInput.value = chatHistory[--chatHistoryPos] !== undefined ? chatHistory[chatHistoryPos] : ''
60+
} else if (e.keyCode === 40) {
61+
if (chatHistoryPos === chatHistory.length) return
62+
chatInput.value = chatHistory[++chatHistoryPos] !== undefined ? chatHistory[chatHistoryPos] : ''
63+
}
64+
}
65+
66+
// Chat events
67+
document.onkeypress = function (e) {
68+
e = e || window.event
69+
if (inChat === false) {
70+
if (e.code === 'KeyT') {
71+
enableChat(false)
72+
}
73+
74+
if (e.code === 'Slash') {
75+
enableChat(true)
76+
}
77+
return false
78+
}
79+
80+
if (!inChat) return
81+
e.stopPropagation()
82+
if (e.code === 'Enter') {
83+
chatHistory.push(chatInput.value)
84+
/* TODO: mineweb._client */ client.write('chat', {
85+
message: chatInput.value
86+
})
87+
disableChat()
88+
}
89+
}
90+
// Enable inputs back when focused
91+
/* document.addEventListener("pointerlockchange", function(event) {
92+
const canvas = document.getElementById("noa-canvas");
93+
if (
94+
document.pointerLockElement === canvas ||
95+
document.mozPointerLockElement === canvas
96+
) {
97+
// Someone focused the game back so we hide chat.
98+
inChat = false;
99+
hideChat();
100+
}
101+
}); */
102+
function enableChat (isCommand) {
103+
// Set inChat value
104+
inChat = true
105+
// Exit the pointer lock
106+
document.exitPointerLock()
107+
// Show chat input
108+
chatInput.style.display = 'block'
109+
// Show extended chat history
110+
chat.style.maxHeight = 'calc(90px * 8)'
111+
chat.scrollTop = chat.scrollHeight // Stay bottom of the list
112+
if (isCommand) { // handle commands
113+
chatInput.value = '/'
114+
}
115+
// Focus element
116+
chatInput.focus()
117+
// Disable controls
118+
// mineweb._noa.inputs.disabled = true;
119+
chatHistoryPos = chatHistory.length
120+
}
121+
function disableChat () {
122+
// Set inChat value
123+
inChat = false
124+
// Hide chat
125+
hideChat()
126+
127+
renderer.domElement.requestPointerLock()
128+
// Enable controls
129+
// mineweb._noa.inputs.disabled = false;
130+
// Focus noa again
131+
/* const canvas = document.getElementById("noa-canvas");
132+
canvas.requestPointerLock =
133+
canvas.requestPointerLock || canvas.mozRequestPointerLock;
134+
canvas.requestPointerLock(); */
135+
}
136+
function hideChat () {
137+
// Clear chat input
138+
chatInput.value = ''
139+
// Unfocus it
140+
chatInput.blur()
141+
// Hide it
142+
chatInput.style.display = 'none'
143+
// Hide extended chat history
144+
chat.style.maxHeight = 'calc(90px * 4)'
145+
chat.scrollTop = chat.scrollHeight // Stay bottom of the list
146+
}
147+
148+
function readExtra (extra) {
149+
const shouldReturn = []
150+
for (const i in extra) {
151+
if (extra[i].text) {
152+
shouldReturn.push({
153+
text: extra[i].text,
154+
color: extra[i].color,
155+
bold: !!extra[i].bold,
156+
italic: !!extra[i].italic,
157+
underlined: !!extra[i].underlined,
158+
strikethrough: !!extra[i].strikethrough,
159+
obfuscated: !!extra[i].obfuscated
160+
})
161+
} else {
162+
readExtra(extra).forEach(function (el) {
163+
shouldReturn.push(el)
164+
})
165+
}
166+
}
167+
return shouldReturn
168+
}
169+
// Client part
170+
/* TODO: mineweb._client */ client.on('chat', function (packet) {
171+
// Reading of chat message
172+
const fullmessage = JSON.parse(packet.message.toString())
173+
let msglist = []
174+
if (
175+
fullmessage.extra &&
176+
fullmessage.extra.length > 0 &&
177+
!fullmessage.translate
178+
) {
179+
msglist = readExtra(fullmessage.extra)
180+
} else if (fullmessage.text && fullmessage.text.length > 0) {
181+
msglist.push({ text: fullmessage.text, color: undefined })
182+
} else if (dictionary[fullmessage.translate]) {
183+
let msg = dictionary[fullmessage.translate]
184+
fullmessage.with.forEach(obj => {
185+
if (obj.insertion && obj.text) {
186+
msg = msg.replace('%s', obj.text)
187+
}
188+
if (obj.extra) {
189+
if (obj.text && obj.text.length > 0) {
190+
msglist.push({ text: obj.text, color: undefined })
191+
} else {
192+
const text = readExtra(obj.extra)
193+
if (text.length > 1) {
194+
console.log('Unsupported chat alert :(')
195+
}
196+
msg = msg.replace('%s', text[0].text)
197+
msglist.push({ text: msg, color: undefined })
198+
}
199+
}
200+
})
201+
} else {
202+
// msglist.push({
203+
// text:
204+
// "Unsupported message (Please report this):\n" +
205+
// JSON.stringify(fullmessage),
206+
// color: undefined
207+
// });
208+
}
209+
const li = document.createElement('li')
210+
msglist.forEach(msg => {
211+
const span = document.createElement('span')
212+
span.appendChild(document.createTextNode(msg.text))
213+
span.setAttribute(
214+
'style',
215+
`${msg.color ? styles[msg.color.toLowerCase()] : styles.white}; ${
216+
msg.bold ? styles.bold + ';' : ''
217+
}${msg.italic ? styles.italic + ';' : ''}${
218+
msg.strikethrough ? styles.strikethrough + ';' : ''
219+
}${msg.underlined ? styles.underlined + ';' : ''}`
220+
)
221+
li.appendChild(span)
222+
})
223+
chat.appendChild(li)
224+
chat.scrollTop = chat.scrollHeight // Stay bottom of the list
225+
})
226+
}

dns.js renamed to lib/dns.js

File renamed without changes.
File renamed without changes.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,10 @@
3232
"homepage": "https://github.com/PrismarineJS/prismarine-web-client#readme",
3333
"dependencies": {
3434
"body-parser": "^1.19.0",
35+
"compression": "^1.7.4",
3536
"express": "^4.17.1",
3637
"net-browserify": "^0.2.4",
37-
"request": "^2.88.2",
38-
"compression": "^1.7.4"
38+
"request": "^2.88.2"
3939
},
4040
"devDependencies": {
4141
"assert": "^2.0.0",

webpack.config.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ const config = {
3838
timers: require.resolve('timers-browserify'),
3939
// fs: require.resolve("fs-memory/singleton"),
4040
child_process: false,
41-
perf_hooks: path.resolve(__dirname, 'perf_hooks_replacement.js'),
42-
dns: path.resolve(__dirname, 'dns.js')
41+
perf_hooks: path.resolve(__dirname, 'lib/perf_hooks_replacement.js'),
42+
dns: path.resolve(__dirname, 'lib/dns.js')
4343
}
4444
},
4545
plugins: [

0 commit comments

Comments
 (0)