How do I read Minecraft packets? - minecraft

I'm not familiar with packets and trying to make my own implementation of Minecraft server.
I used net.createServer() and the incoming data looks like this
� localhostc�
�0�H��name����=�0�"0
��]�
�ܩ X�Ox��R��Y������[�#��)Ҡ��
����{�h���k��>#A�"Qv�� ����]��;�7HA��>�t�����bإ7~T.�>[����jÅ(�� �+ӂ7˟nɟ(�=gé��P�¿û�ª�øþ¥¿´��¨ò͵¯��±Ö��¦Ì��Ç�®Á�ð�Ú�݃��¡ÄÜ«Ë��»�úÛ��º��èã��ۿî�æ�ø��Î�ðê�Á؍¦çÄ�������
"��)�q웇x*z^�N�Y�i`_��F`��:�H�x���d��5Z(�����1VE
ܖ$tC6QH]��P���:���Q���y�`��AF��}89�U���7R���R�`��#g�ʉ�d})�w�&��&c��,Y?e���H5wF�:�Q��8�2���NG��o��4�#��G�"^ֵ���Os�Hpg�L�S���gS=&"IK
/B�3���i��(�i�p�T�ΣaQ!r{�"Hqr^�;�
����KE~�|6�v�)̒3��EL��,A�<%�
�����6c�LU�NE5�4j^O���
�xZL���o&�nL�G�--I������
��O�
ht,�
C��z� �[�:�ew�w0N$�$\N�B���iS����j�\i#���Q��0S�"�lL\�4��b;�������<A��0ni�=�A��n��a�N�
How do I read this and convert to JSON?
My code
import { createServer } from "net"
const server = createServer()
server.on("connection", (socket) => {
socket.on("connect", () => {
console.log("Connected")
})
socket.on("data", (packet) => {
console.log(packet.toString())
})
})
server.listen(25565, () => {
console.log("Listening")
})
I'm trying to make this with minimal dependencies, so I searched about this a lot but I could not find how to do this.

Related

How to mock expo-camera requestCameraPermissionsAsync() response?

I am trying to do a unit test to one of my react native components.
One scenario requires me to mock expo-camera requestCameraPermissionsAsync() method but don't know how. What I'm trying to do is to mock the status to always have the granted value.
Initial approach, below:
jest.mock('expo-camera', () => {
const PermissionsCamera = jest.requireActual('expo-camera');
return {
...PermissionsCamera,
requestCameraPermissionsAsync: () =>
new Promise(resolve => resolve({granted: true, status: 'granted'})),
};
});
But that doesn't work. Need help, is there something wrong with the code above? Thank you
Update:
How I implemented in the component:
import {Camera} from 'expo-camera'
useEffect(() => {
(async () => {
const {status} = await Camera.requestCameraPermissionsAsync();
// additional logic when status is equal to 'granted'
})();
}, []);

Fetch more data in RxJs

I have some problem with apply fetching "more" data using fromFetch from rxjs.
I have project with React and RXJS. Currently I'm using something like this:
const stream$ = fromFetch('https://pokeapi.co/api/v2/pokemon?limit=100', {
selector: response => response.json()
}).subscribe(data => console.log(data));
But! I would like to change limit dynamically, when I click button or even better - when I scroll to the very bottom of my website. How to make something like this?
So that, based on some interaction, the limit would change?
The way your observable work in your case it's a request-response. You're declaring stream$ to be an observable that when someone subscribes it will make a request with limit=100.
There are different ways of solving this... The most straightforward would be:
const getPokemon$ = limit =>
fromFetch('https://pokeapi.co/api/v2/pokemon?limit=' + limit, {
selector: response => response.json()
});
const MyComponent = () => {
// ...
useEffect(() => {
const sub = getPokemon$(limit).subscribe(res => console.log(res));
return () => sub.unsubscribe();
}, [limit])
// ...
}
Another option, probably a bit more reactive but harder to follow for others, would be to declare another stream which sets the limit:
const limit$ = new BehaviorSubject(100)
const pokemon$ = limit$.pipe(
switchMap(limit => fromFetch('https://pokeapi.co/api/v2/pokemon?limit=' + limit, {
selector: response => response.json()
}))
);
// In your component
const MyComponent = () => {
// ...
useEffect(() => {
const sub = pokemon$.subscribe(res => console.log(res));
return () => sub.unsubscribe();
}, [])
changeLimit = (newLimit) => limit$.next(newLimit)
// ...
}
In this other solution, you're declaring how pokemon$ should react to changes on limit$, and you can set limit$ from any other component you want.

How to share response data across multiple suites?

Let's say we have the following suite:
describe('Devices', () => {
describe('Master Data Set-Up', () => {
it('should create the device if necessary', () => {
cy.createDevice()
its('body.id')
.as('deviceId');
});
});
describe('Test Suite 1', () => {
it('should allow to send data to device', () => {
cy.get('#deviceId').then((deviceId) => {
cy.sendData(deviceId, 'Some Data');
});
});
});
});
So, we have a set up suite that creates master data. This is a simplified version, actually it contains a couple of it specs and I'd like to keep it like that because it's better to read in the Cypress output.
Then, there is the actual test suite that want's to use data that has previously been created. In this case a server generated id that should be used for another REST call.
This is assuming, that cy.createDevice and cy.sendData are custom commands available that internally use cy.request.
When running that, cy.get('#deviceId') fails because aliases are not shared across describe blocks AFAIK. I tried to use let deviceId but it's undefined as it is not yet available when the test specs are processed.
What is a proper way to do this?
I believe this will be better solution, as cypress is asynchronous so it's better to write it on file and read it
describe('Devices', () => {
describe('Master Data Set-Up', () => {
it('should create the device if necessary', () => {
cy.createDevice()
......
cy.writeFile('deviceId.txt', body.id)
});
});
describe('Test Suite 1', () => {
it('should allow to send data to device', () => {
cy.readFile('deviceId.txt').then((device_id) => {
cy.sendData(device_id, 'Some Data');
})
});
});
});
Upvote for #ArekKhatry's idea, but to be safe I would obtain the the id in a before(). If you ever run tests in parallel, grabbing data from one test to use in another would be flaky.
Note that running cy.createDevice().its('body.id') in the before() still gives you the same test coverage as running inside it(), i.e it tests that the request succeeds and the return value has an id.
The file should be written to cypress/fixtures, otherwise it will write to the project root causing untidy pollution of the file structure.
Also, the id is returned from cy.request() as a number, but must be stringifyed in order to write to a text file.
Here's my variant
describe('Devices', () => {
before(() => {
cy.createDevice()
.its('body.id')
.then(id => {
cy.writeFile('cypress/fixtures/deviceId.txt', id.toString());
cy.log(`Created device: ${id}`);
});
});
describe('Test Suite 1', () => {
it('should allow to send data to device', () => {
cy.fixture('deviceId') // can use simpler cy.fixture here
.then(device_id => { // returned as a string here
const id = parseInt(device_id); // may need to parse to number?
cy.sendData(id, 'Some Data');
})
});
});
});
Ok, so first thanks to Aloysius and Arek for their answers. But I had the gut feeling that there must be some easier way to do this that writing an Id to a file.
As I mentioned before, I had issues with my first attempt to use a global variable:
I tried to use let deviceId but it's undefined as it is not yet
available when the test specs are processed.
I really wanted to understand, why this did not work and did some console debugging.
I added a console log:
describe('Devices', () => {
console.log('Loading test suites...')
(...)
});
When running the tests, I saw the log output twice, once after the first describe block where the device id was stored and then a second time after the master data was written.
Actually, I found out that this issue was cause by the following known Cypress issue:
https://github.com/cypress-io/cypress/issues/2777
After setting the baseUrl, it actually works:
describe('Devices', () => {
let deviceId;
before( () => {
Cypress.config('baseUrl', Cypress.env('system_url'))
cy.visit('/');
})
describe('Master Data Set-Up', () => {
it('should create the device if necessary', () => {
cy.createDevice()
.its('body.id')
.then((id) => {
deviceId = id;
});
});
});
describe('Test Suite 1', () => {
it('should allow to send data to device', () => {
cy.sendData(deviceId, 'Some Data');
});
});
});

Relay subscriptions not working with react-native

I'm using Express Graphql server with react native and Relay. My device does connects to the subscription but it does not subscribe to it. Here's my index.js on the server
const subscriptionServer = SubscriptionServer.create(
{
execute,
subscribe,
schema,
onOperation: (message, params, webSocket) => {
console.log(params)
return params;
},
onConnect: () => {
// My device does connects
console.log("client connected")
}
},
{
server,
path: '/subscriptions'
},
);
app.use('/graphql', graphqlHTTP({
schema,
graphiql: true
}));
app.use('/graphiql', graphiqlExpress({
endpointURL: '/graphql',
subscriptionsEndpoint: `ws://127.0.0.1:8080/subscriptions`
}));
server.listen(PORT, ()=> {
console.log("Groceries running on port " + PORT)
console.log(
`subscriptions is now running on ws://localhost:${PORT}/subscriptions'}`
);
});
The resolver for subscription on the server, it was quite troublesome to figure out since everyone is using executable schema from apolloGraphql.
export default {
type: OrderEdges,
args: {
ShopId: {type: GraphQLID},
},
subscribe: withFilter(() => pubsub.asyncIterator('orderConfirmed'), (payload, variables) => {
console.log(payload)
console.log(variables)
return payload.orderConfirmed.node.ShopId == variables.ShopId;
}),
}
Now the react-native client. My subscription setup with relay environment.
const setupSubscriptions = (config, variables, cacheConfig, observer) => {
const query = config.text; //does console logs the query
const subscriptionClient = new SubscriptionClient(`ws://192.168.0.100:8080/subscriptions`, {reconnect:true});
subscriptionClient.request({query, variables}, (err, result) => {
console.log(err) // doesn't get call inside the request method
observer.onNext(data:result)
})
}
My subscription method,
export default function() {
const variables = {
ShopId: shop.getShop()[0].id
}
requestSubscription(
environment,
{
subscription,
variables,
onCompleted: (res, err) => {
console.log(res)
console.log(err)
},
updater: (store) => {...},
onError: error => console.error(error),
onNext: (response) => {console.log(response)}
});
}
the component where I'm calling to subscribe,
import subscription from '../../GraphQLQueries/subscriptions/orderConfirmed';
class OrdersBox extends React.Component {
constructor(props) {
super(props);
}
componentDidMount() {
//initializing subscription
orderSubscriptions();
}
When the device starts the app, my device is connected to the web socket as I can see the console.log statement inside the onConnect method in SubscriptionServer. But when the payload is published after a mutation, the subscribe method doesn't get called. I can't seem to figure out what I'm doing wrong. Maybe it's some react-native specific config that I'm missing cuz everything seems to work fine when I test it on graphiql.
I can't find any example of react-native and relay subscriptions used with express graphql.
note: Everything is working when I use subscription with graphiql. But not with react-native and relay.
Thanks in advance guys
....
I wasn't returning the subscriptionClient.request method. Adding a return statement solved the problem. You don't have to return when using subscribe method in subscriptions-transport-ws#0.8.3. But version 0.9.1 replaces the subscribe function with request which does require it to return.
try:
function setupSubscription(config, variables, cacheConfig, observer) {
const query = config.text;
const subscriptionClient = new SubscriptionClient(websocketURL, {
reconnect: true
});
const client = subscriptionClient.request({ query, variables }).subscribe({
next: result => {
observer.onNext({ data: result.data });
},
complete: () => {
observer.onCompleted();
},
error: error => {
observer.onError(error);
}
});
return {
dispose: client.unsubscribe
};
}
subscriptions-transport-ws#0.9.1

Compressing base64 encoded images in React-Native on Android does not recognise 'data' protocol

Issue
Within a React-Native (0.43) application we are using a component that uses a SectionList to render photos sorted by day. Each section can contain multiple images. Photos are taken using the react-native-image-crop-picker library and uploaded to the backend, or queued locally if no internet connection is available, encoded in base64 format. The image resolution is set to 800x800 pixels (requirement for other purposes of the images). On phones with lower memory, rendering ~20 images will crash the app due to insufficient memory. This issue can only be reproduced on low-end Android phones but I expect this to be a low memory issue and not related to the OS. To tackle this issue, thumbnails need to be generated to test if this is the case. Independent of when these thumbnails are generated (before sending to server or on-the-fly before loading component). The code below works fine for iOS but for Android it throws the error: Unknown protocol: data which comes from the ImageEditor.cropImage() function.
Snippet from main .js file
//The mergeReduxWithMeteor function takes care of merging the redux state,
//containing images not yet uploaded to the server,
//and the Meteor data as received by the server.
//No issues here...
helpers.mergeReduxWithMeteor(props.photoStore, props.SynergySummaryReady ? props.SynergyData : [])
//The imageHelper.compressPhoto does the actual compression
//No issues with the promise chain as is.
.then((data) => {
return Promise.all(data.map(imageHelper.compressPhoto))
})
// The remaining functions take care of the formatting for the SectionList.
// No issues here either... :)
.then((data) => {
return helpers.clusterDataByDay(data)
})
//We populate the resulting data in the state that is used for the SectionList
.then((data) => {
this.setState({NotHorusData: data})
})
.catch((error) => console.error(error))
imageHelper.compressphoto()
export function compressPhoto(photo) {
return new Promise((resolve, reject) => {
let imageSize = {
offset: {
x: 0,
y: 0
},
size: {
width: IMAGE_SIZE,
height: IMAGE_SIZE
},
displaySize: {
width: IMAGE_TARGET_SIZE,
height: IMAGE_TARGET_SIZE,
},
resizeMode: 'contain'
}
ImageEditor.cropImage(`data:image/jpeg;base64,${photo.data.userPhoto}`, imageSize, (imageURI) => {
ImageStore.getBase64ForTag(imageURI, (base64Data) => {
resolve({
...photo,
data: {
...photo.data,
userPhoto: base64Data,
}
})
}, (error) => reject(error))
}, (error) => reject(error))
})
}
Approach 1: Fix data protocol issue on Android
Issue on Github from RN addresses the same issue but no solution is provided.
Approach 2: Bypass data protocol issue by providing uri on Android
Although less favourable due to the added communication/delay, another approach is to avoid the data protocol issue by providing a temporary URI provided by ImageStore. See the adapted code below for Android.
if(Platform.OS === 'android'){
ImageStore.addImageFromBase64(`data:image/jpeg;base64,${photo.data.userPhoto}`, (tempURI) => {
ImageEditor.cropImage(tempURI, imageSize, (imageURI) => {
ImageStore.getBase64ForTag(imageURI, (base64Data) => {
ImageStore.removeImageForTag(tempURI)
resolve({
...photo,
data: {
...photo.data,
userPhoto: base64Data,
}
})
}, (error) => reject(error))
}, (error) => reject(error))
}, (error) => reject(error))
}
Unfortunately ImageStore.addImageFromBase64 is not recognised on Android.
Does anyone have any experience with ImageEditor and ImageStore on Android that might be helpful in this situation? Any other approaches are welcome too!
I managed to resolve the issue with the use of react-native-fetch-blob and react-native-image-resizer for both iOS and Android. Performance is unexpectedly good in comparison to the implementation in the question above. I shared the code below for others to use :)
export function compressPhoto(photo) {
return new Promise((resolve, reject) => {
let tempUri = `${cache}/Vire_${photo.data.userPhotoDate}.jpg`
fs.writeFile(tempUri, photo.data.userPhoto, "base64")
.then(() => {
ImageResizer.createResizedImage(
`file:${tempUri}`, IMAGE_TARGET_SIZE, IMAGE_TARGET_SIZE, "JPEG", 100, 0).then((resizedImageUri) => {
fs.readFile(`${resizedImageUri}`, "base64")
.then( data => {
resolve({...photo, data: { ...photo.data, userPhoto: data }})
})
.catch(error => reject(`readFile:error: ${error}`))
},
(error) => reject(`createResizedImage:error: ${error}`)
)
})
.catch( error => {
reject(`writeFile:error: ${error}`)
})
})
}
The gist is storing base64 encoded picture in the cache-directory and using imageResizer to fetch the image, compress it, and read it again in base64 for use.